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

📄 acache.c

📁 非常好的dns解析软件
💻 C
📖 第 1 页 / 共 4 页
字号:
	INSIST(ISC_LIST_EMPTY(dbentry->originlist) &&	       ISC_LIST_EMPTY(dbentry->referlist));	bucket = isc_hash_calc((const unsigned char *)&db,			       sizeof(db), ISC_TRUE) % DBBUCKETS;	ISC_LIST_UNLINK(acache->dbbucket[bucket], dbentry, link);	dns_db_detach(&dbentry->db);	isc_mem_put(acache->mctx, dbentry, sizeof(*dbentry));	acache->dbentries--;	acache->stats.deleted++;	UNLOCK(&acache->lock);	return (ISC_R_SUCCESS);}isc_result_tdns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb,		       void (*callback)(dns_acacheentry_t *, void **),		       void *cbarg, dns_acacheentry_t **entryp){	dns_acacheentry_t *newentry;	isc_result_t result;	isc_uint32_t r;	REQUIRE(DNS_ACACHE_VALID(acache));	REQUIRE(entryp != NULL && *entryp == NULL);	REQUIRE(origdb != NULL);	/* 	 * Should we exceed our memory limit for some reason (for 	 * example, if the cleaner does not run aggressively enough), 	 * then we will not create additional entries.	 *	 * XXXSK: It might be better to lock the acache->cleaner->lock,	 * but locking may be an expensive bottleneck. If we misread 	 * the value, we will occasionally refuse to create a few 	 * cache entries, or create a few that we should not. I do not	 * expect this to happen often, and it will not have very bad	 * effects when it does. So no lock for now.	 */	if (acache->cleaner.overmem) {		acache->stats.overmem_nocreates++; /* XXXSK danger: unlocked! */		return (ISC_R_NORESOURCES);	}	newentry = isc_mem_get(acache->mctx, sizeof(*newentry));	if (newentry == NULL) {		acache->stats.nomem++;  /* XXXMLG danger: unlocked! */		return (ISC_R_NOMEMORY);	}	isc_random_get(&r);	newentry->locknum = r % DEFAULT_ACACHE_ENTRY_LOCK_COUNT;		result = isc_refcount_init(&newentry->references, 1);	if (result != ISC_R_SUCCESS) {		isc_mem_put(acache->mctx, newentry, sizeof(*newentry));		return (result);	};	ISC_LINK_INIT(newentry, link);	ISC_LINK_INIT(newentry, olink);	ISC_LINK_INIT(newentry, rlink);	newentry->acache = NULL;	dns_acache_attach(acache, &newentry->acache);	newentry->zone = NULL;	newentry->db = NULL;	newentry->version = NULL;	newentry->node = NULL;	newentry->foundname = NULL;	newentry->callback = callback;	newentry->cbarg = cbarg;	newentry->origdb = NULL;	dns_db_attach(origdb, &newentry->origdb);	isc_stdtime_get(&newentry->lastused);	newentry->magic = ACACHEENTRY_MAGIC;	*entryp = newentry;	return (ISC_R_SUCCESS);}isc_result_tdns_acache_getentry(dns_acacheentry_t *entry, dns_zone_t **zonep,		    dns_db_t **dbp, dns_dbversion_t **versionp,		    dns_dbnode_t **nodep, dns_name_t *fname,		    dns_message_t *msg, isc_stdtime_t now){	isc_result_t result = ISC_R_SUCCESS;	dns_rdataset_t *erdataset;	isc_stdtime32_t	now32;	dns_acache_t *acache;	int locknum;	REQUIRE(DNS_ACACHEENTRY_VALID(entry));	REQUIRE(zonep == NULL || *zonep == NULL);	REQUIRE(dbp != NULL && *dbp == NULL);	REQUIRE(versionp != NULL && *versionp == NULL);	REQUIRE(nodep != NULL && *nodep == NULL);	REQUIRE(fname != NULL);	REQUIRE(msg != NULL);	acache = entry->acache;	REQUIRE(DNS_ACACHE_VALID(acache));	locknum = entry->locknum;	ACACHE_LOCK(&acache->entrylocks[locknum], isc_rwlocktype_read);	isc_stdtime_convert32(now, &now32);	acache_storetime(entry, now32);	if (entry->zone != NULL && zonep != NULL)		dns_zone_attach(entry->zone, zonep);	if (entry->db == NULL) {		*dbp = NULL;		*versionp = NULL;	} else {		dns_db_attach(entry->db, dbp);		dns_db_attachversion(entry->db, entry->version, versionp);	}	if (entry->node == NULL)		*nodep = NULL;	else {		dns_db_attachnode(entry->db, entry->node, nodep);		INSIST(entry->foundname != NULL);		dns_name_copy(entry->foundname, fname, NULL);		for (erdataset = ISC_LIST_HEAD(entry->foundname->list);		     erdataset != NULL;		     erdataset = ISC_LIST_NEXT(erdataset, link)) {			dns_rdataset_t *ardataset;			ardataset = NULL;			result = dns_message_gettemprdataset(msg, &ardataset);			if (result != ISC_R_SUCCESS) {				ACACHE_UNLOCK(&acache->entrylocks[locknum],					      isc_rwlocktype_read);				goto fail;			}			/*			 * XXXJT: if we simply clone the rdataset, we'll get			 * lost wrt cyclic ordering.  We'll need an additional			 * trick to get the latest counter from the original			 * header.			 */			dns_rdataset_init(ardataset);			dns_rdataset_clone(erdataset, ardataset);			ISC_LIST_APPEND(fname->list, ardataset, link);		}	}	entry->acache->stats.hits++; /* XXXMLG danger: unlocked! */	entry->acache->stats.queries++;	ACACHE_UNLOCK(&acache->entrylocks[locknum], isc_rwlocktype_read);	return (result);  fail:	while ((erdataset = ISC_LIST_HEAD(fname->list)) != NULL) {		ISC_LIST_UNLINK(fname->list, erdataset, link);		dns_rdataset_disassociate(erdataset);		dns_message_puttemprdataset(msg, &erdataset);	}	if (*nodep != NULL)		dns_db_detachnode(*dbp, nodep);	if (*versionp != NULL)		dns_db_closeversion(*dbp, versionp, ISC_FALSE);	if (*dbp != NULL)		dns_db_detach(dbp);	if (zonep != NULL && *zonep != NULL)		dns_zone_detach(zonep);	return (result);}isc_result_tdns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry,		    dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,		    dns_dbnode_t *node, dns_name_t *fname){	isc_result_t result;	dbentry_t *odbent;	dbentry_t *rdbent = NULL;	isc_boolean_t close_version = ISC_FALSE;	dns_acacheentry_t *dummy_entry = NULL;	REQUIRE(DNS_ACACHE_VALID(acache));	REQUIRE(DNS_ACACHEENTRY_VALID(entry));	LOCK(&acache->lock);	/* XXX: need to lock it here for ordering */	ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write);	/* Set zone */	if (zone != NULL)		dns_zone_attach(zone, &entry->zone);	/* Set DB */	if (db != NULL)		dns_db_attach(db, &entry->db);	/*	 * Set DB version.  If the version is not given by the caller,	 * which is the case for glue or cache DBs, use the current version.	 */	if (version == NULL) {		if (db != NULL) {			dns_db_currentversion(db, &version);			close_version = ISC_TRUE;		}	}	if (version != NULL) {		INSIST(db != NULL);		dns_db_attachversion(db, version, &entry->version);	}	if (close_version)		dns_db_closeversion(db, &version, ISC_FALSE);	/* Set DB node. */	if (node != NULL) {		INSIST(db != NULL);		dns_db_attachnode(db, node, &entry->node);	}	/*	 * Set list of the corresponding rdatasets, if given.	 * To minimize the overhead and memory consumption, we'll do this for	 * positive cache only, in which case the DB node is non NULL.	 * We do not want to cache incomplete information, so give up the	 * entire entry when a memory shortage happen during the process.	 */	if (node != NULL) {		dns_rdataset_t *ardataset, *crdataset;		entry->foundname = isc_mem_get(acache->mctx,					       sizeof(*entry->foundname));		if (entry->foundname == NULL) {			result = ISC_R_NOMEMORY;			goto fail;		}		dns_name_init(entry->foundname, NULL);		result = dns_name_dup(fname, acache->mctx,				      entry->foundname);		if (result != ISC_R_SUCCESS)			goto fail;		for (ardataset = ISC_LIST_HEAD(fname->list);		     ardataset != NULL;		     ardataset = ISC_LIST_NEXT(ardataset, link)) {			crdataset = isc_mem_get(acache->mctx,						sizeof(*crdataset));			if (crdataset == NULL) {				result = ISC_R_NOMEMORY;				goto fail;			}			dns_rdataset_init(crdataset);			dns_rdataset_clone(ardataset, crdataset);			ISC_LIST_APPEND(entry->foundname->list, crdataset,					link);		}	}	odbent = NULL;	result = finddbent(acache, entry->origdb, &odbent);	if (result != ISC_R_SUCCESS)		goto fail;	if (db != NULL) {		rdbent = NULL;		result = finddbent(acache, db, &rdbent);		if (result != ISC_R_SUCCESS)			goto fail;	}	ISC_LIST_APPEND(acache->entries, entry, link);	ISC_LIST_APPEND(odbent->originlist, entry, olink);	if (rdbent != NULL)		ISC_LIST_APPEND(rdbent->referlist, entry, rlink);	/*	 * The additional cache needs an implicit reference to entries in its	 * link.	 */	dns_acache_attachentry(entry, &dummy_entry);	ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],		      isc_rwlocktype_write);	acache->stats.adds++;	UNLOCK(&acache->lock);	return (ISC_R_SUCCESS); fail:	clear_entry(acache, entry);	ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],		      isc_rwlocktype_write);	UNLOCK(&acache->lock);	return (result);}voiddns_acache_cancelentry(dns_acacheentry_t *entry) {	dns_acache_t *acache = entry->acache;	REQUIRE(DNS_ACACHEENTRY_VALID(entry));	INSIST(DNS_ACACHE_VALID(acache));	LOCK(&acache->lock);	ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write);	/*	 * Release dependencies stored in this entry as much as possible.	 * The main link cannot be released, since the acache object has	 * a reference to this entry; the empty entry will be released in	 * the next cleaning action.	 */	unlink_dbentries(acache, entry);	clear_entry(entry->acache, entry);	entry->callback = NULL;	entry->cbarg = NULL;	ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],		      isc_rwlocktype_write);	UNLOCK(&acache->lock);}voiddns_acache_attachentry(dns_acacheentry_t *source,		       dns_acacheentry_t **targetp){	REQUIRE(DNS_ACACHEENTRY_VALID(source));	REQUIRE(targetp != NULL && *targetp == NULL);	isc_refcount_increment(&source->references, NULL);	*targetp = source;}voiddns_acache_detachentry(dns_acacheentry_t **entryp) {	dns_acacheentry_t *entry;	unsigned int refs;	REQUIRE(entryp != NULL && DNS_ACACHEENTRY_VALID(*entryp));	entry = *entryp;	isc_refcount_decrement(&entry->references, &refs);	/*	 * If there are no references to the entry, the entry must have been	 * unlinked and can be destroyed safely.	 */	if (refs == 0) {		INSIST(!ISC_LINK_LINKED(entry, link));		(*entryp)->acache->stats.deleted++;		destroy_entry(entry);	}	*entryp = NULL;}voiddns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t) {	isc_interval_t interval;	isc_result_t result;	REQUIRE(DNS_ACACHE_VALID(acache));	ATRACE("dns_acache_setcleaninginterval");	LOCK(&acache->lock);	/*	 * It may be the case that the acache has already shut down.	 * If so, it has no timer.  (Not sure if this can really happen.)	 */	if (acache->cleaner.cleaning_timer == NULL)		goto unlock;	acache->cleaner.cleaning_interval = t;	if (t == 0) {		result = isc_timer_reset(acache->cleaner.cleaning_timer,					 isc_timertype_inactive,					 NULL, NULL, ISC_TRUE);	} else {		isc_interval_set(&interval, acache->cleaner.cleaning_interval,				 0);		result = isc_timer_reset(acache->cleaner.cleaning_timer,					 isc_timertype_ticker,					 NULL, &interval, ISC_FALSE);	}	if (result != ISC_R_SUCCESS)			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_ACACHE, ISC_LOG_WARNING,			      "could not set acache cleaning interval: %s",			      isc_result_totext(result));	else		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_ACACHE, ISC_LOG_NOTICE,			      "acache %p cleaning interval set to %d.",			      acache, t); unlock:	UNLOCK(&acache->lock);}/* * This function was derived from cache.c:dns_cache_setcachesize().  See the * function for more details about the logic. */voiddns_acache_setcachesize(dns_acache_t *acache, isc_uint32_t size) {	isc_uint32_t lowater;	isc_uint32_t hiwater;	REQUIRE(DNS_ACACHE_VALID(acache));	if (size != 0 && size < DNS_ACACHE_MINSIZE)		size = DNS_ACACHE_MINSIZE;	hiwater = size - (size >> 3);	lowater = size - (size >> 2);	if (size == 0 || hiwater == 0 || lowater == 0)		isc_mem_setwater(acache->mctx, water, acache, 0, 0);	else		isc_mem_setwater(acache->mctx, water, acache,				 hiwater, lowater);}

⌨️ 快捷键说明

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