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

📄 adb.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
	dns_adbname_t *name;	dns_adbname_t *next_name;	isc_result_t result = ISC_FALSE;	DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket);	LOCK(&adb->namelocks[bucket]);	if (adb->name_sd[bucket]) {		UNLOCK(&adb->namelocks[bucket]);		return (result);	}	name = ISC_LIST_HEAD(adb->names[bucket]);	while (name != NULL) {		next_name = ISC_LIST_NEXT(name, plink);		INSIST(result == ISC_FALSE);		result = check_expire_namehooks(name, now);		if (!result)			result = check_expire_name(&name, now);		name = next_name;	}	UNLOCK(&adb->namelocks[bucket]);	return (result);}/* * ADB must be locked, and no other locks held. */static isc_boolean_tcleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {	dns_adbentry_t *entry, *next_entry;	isc_boolean_t result = ISC_FALSE;	DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket);	LOCK(&adb->entrylocks[bucket]);	entry = ISC_LIST_HEAD(adb->entries[bucket]);	while (entry != NULL) {		next_entry = ISC_LIST_NEXT(entry, plink);		INSIST(result == ISC_FALSE);		result = check_expire_entry(adb, &entry, now);		entry = next_entry;	}	UNLOCK(&adb->entrylocks[bucket]);	return (result);}static voidtimer_cleanup(isc_task_t *task, isc_event_t *ev) {	dns_adb_t *adb;	isc_stdtime_t now;	unsigned int i;	UNUSED(task);	adb = ev->ev_arg;	INSIST(DNS_ADB_VALID(adb));	LOCK(&adb->lock);	isc_stdtime_get(&now);	for (i = 0 ; i < CLEAN_BUCKETS ; i++) {		/*		 * Call our cleanup routines.		 */		RUNTIME_CHECK(cleanup_names(adb, adb->next_cleanbucket, now) ==			      ISC_FALSE);		RUNTIME_CHECK(cleanup_entries(adb, adb->next_cleanbucket, now)			      == ISC_FALSE);		/*		 * Set the next bucket to be cleaned.		 */		adb->next_cleanbucket++;		if (adb->next_cleanbucket >= NBUCKETS) {			adb->next_cleanbucket = 0;#ifdef DUMP_ADB_AFTER_CLEANING			dump_adb(adb, stdout, ISC_TRUE);#endif		}	}	/*	 * Reset the timer.	 * XXXDCL isc_timer_reset might return ISC_R_UNEXPECTED or	 * ISC_R_NOMEMORY, but it isn't clear what could be done here	 * if either one of those things happened.	 */	(void)isc_timer_reset(adb->timer, isc_timertype_once, NULL,			      &adb->tick_interval, ISC_FALSE);	UNLOCK(&adb->lock);	isc_event_free(&ev);}static voiddestroy(dns_adb_t *adb) {	adb->magic = 0;	/*	 * The timer is already dead, from the task's shutdown callback.	 */	isc_task_detach(&adb->task);	isc_mempool_destroy(&adb->nmp);	isc_mempool_destroy(&adb->nhmp);	isc_mempool_destroy(&adb->zimp);	isc_mempool_destroy(&adb->emp);	isc_mempool_destroy(&adb->ahmp);	isc_mempool_destroy(&adb->aimp);	isc_mempool_destroy(&adb->afmp);	isc_mempool_destroy(&adb->af6mp);	isc_mutexblock_destroy(adb->entrylocks, NBUCKETS);	isc_mutexblock_destroy(adb->namelocks, NBUCKETS);	DESTROYLOCK(&adb->reflock);	DESTROYLOCK(&adb->lock);	DESTROYLOCK(&adb->mplock);	isc_mem_put(adb->mctx, adb, sizeof (dns_adb_t));}/* * Public functions. */isc_result_tdns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,	       isc_taskmgr_t *taskmgr, dns_adb_t **newadb){	dns_adb_t *adb;	isc_result_t result;	int i;	REQUIRE(mem != NULL);	REQUIRE(view != NULL);	REQUIRE(timermgr != NULL);	REQUIRE(taskmgr != NULL);	REQUIRE(newadb != NULL && *newadb == NULL);	adb = isc_mem_get(mem, sizeof (dns_adb_t));	if (adb == NULL)		return (ISC_R_NOMEMORY);	/*	 * Initialize things here that cannot fail, and especially things	 * that must be NULL for the error return to work properly.	 */	adb->magic = 0;	adb->erefcnt = 1;	adb->irefcnt = 0;	adb->nmp = NULL;	adb->nhmp = NULL;	adb->zimp = NULL;	adb->emp = NULL;	adb->ahmp = NULL;	adb->aimp = NULL;	adb->afmp = NULL;	adb->af6mp = NULL;	adb->task = NULL;	adb->timer = NULL;	adb->mctx = mem;	adb->view = view;	adb->timermgr = timermgr;	adb->taskmgr = taskmgr;	adb->next_cleanbucket = 0;	ISC_EVENT_INIT(&adb->cevent, sizeof adb->cevent, 0, NULL,		       DNS_EVENT_ADBCONTROL, shutdown_task, adb,		       adb, NULL, NULL);	adb->cevent_sent = ISC_FALSE;	adb->shutting_down = ISC_FALSE;	ISC_LIST_INIT(adb->whenshutdown);	result = isc_mutex_init(&adb->lock);	if (result != ISC_R_SUCCESS)		goto fail0b;	result = isc_mutex_init(&adb->mplock);	if (result != ISC_R_SUCCESS)		goto fail0c;	result = isc_mutex_init(&adb->reflock);	if (result != ISC_R_SUCCESS)		goto fail0d;	/*	 * Initialize the bucket locks for names and elements.	 * May as well initialize the list heads, too.	 */	result = isc_mutexblock_init(adb->namelocks, NBUCKETS);	if (result != ISC_R_SUCCESS)		goto fail1;	for (i = 0 ; i < NBUCKETS ; i++) {		ISC_LIST_INIT(adb->names[i]);		adb->name_sd[i] = ISC_FALSE;		adb->name_refcnt[i] = 0;		adb->irefcnt++;	}	for (i = 0 ; i < NBUCKETS ; i++) {		ISC_LIST_INIT(adb->entries[i]);		adb->entry_sd[i] = ISC_FALSE;		adb->entry_refcnt[i] = 0;		adb->irefcnt++;	}	result = isc_mutexblock_init(adb->entrylocks, NBUCKETS);	if (result != ISC_R_SUCCESS)		goto fail2;	/*	 * Memory pools	 */#define MPINIT(t, p, n) do { \	result = isc_mempool_create(mem, sizeof (t), &(p)); \	if (result != ISC_R_SUCCESS) \		goto fail3; \	isc_mempool_setfreemax((p), FREE_ITEMS); \	isc_mempool_setfillcount((p), FILL_COUNT); \	isc_mempool_setname((p), n); \	isc_mempool_associatelock((p), &adb->mplock); \} while (0)	MPINIT(dns_adbname_t, adb->nmp, "adbname");	MPINIT(dns_adbnamehook_t, adb->nhmp, "adbnamehook");	MPINIT(dns_adbzoneinfo_t, adb->zimp, "adbzoneinfo");	MPINIT(dns_adbentry_t, adb->emp, "adbentry");	MPINIT(dns_adbfind_t, adb->ahmp, "adbfind");	MPINIT(dns_adbaddrinfo_t, adb->aimp, "adbaddrinfo");	MPINIT(dns_adbfetch_t, adb->afmp, "adbfetch");	MPINIT(dns_adbfetch6_t, adb->af6mp, "adbfetch6");#undef MPINIT	/*	 * Allocate a timer and a task for our periodic cleanup.	 */	result = isc_task_create(adb->taskmgr, 0, &adb->task);	if (result != ISC_R_SUCCESS)		goto fail3;	isc_task_setname(adb->task, "ADB", adb);	/*	 * XXXMLG When this is changed to be a config file option,	 */	isc_interval_set(&adb->tick_interval, CLEAN_SECONDS, 0);	result = isc_timer_create(adb->timermgr, isc_timertype_once,				  NULL, &adb->tick_interval, adb->task,				  timer_cleanup, adb, &adb->timer);	if (result != ISC_R_SUCCESS)		goto fail3;	DP(5,	   "Cleaning interval for adb:  "	   "%u buckets every %u seconds, %u buckets in system, %u cl.interval",	   CLEAN_BUCKETS, CLEAN_SECONDS, NBUCKETS, CLEAN_PERIOD);	/*	 * Normal return.	 */	adb->magic = DNS_ADB_MAGIC;	*newadb = adb;	return (ISC_R_SUCCESS); fail3:	if (adb->task != NULL)		isc_task_detach(&adb->task);	if (adb->timer != NULL)		isc_timer_detach(&adb->timer);	/* clean up entrylocks */	isc_mutexblock_destroy(adb->entrylocks, NBUCKETS); fail2: /* clean up namelocks */	isc_mutexblock_destroy(adb->namelocks, NBUCKETS); fail1: /* clean up only allocated memory */	if (adb->nmp != NULL)		isc_mempool_destroy(&adb->nmp);	if (adb->nhmp != NULL)		isc_mempool_destroy(&adb->nhmp);	if (adb->zimp != NULL)		isc_mempool_destroy(&adb->zimp);	if (adb->emp != NULL)		isc_mempool_destroy(&adb->emp);	if (adb->ahmp != NULL)		isc_mempool_destroy(&adb->ahmp);	if (adb->aimp != NULL)		isc_mempool_destroy(&adb->aimp);	if (adb->afmp != NULL)		isc_mempool_destroy(&adb->afmp);	if (adb->af6mp != NULL)		isc_mempool_destroy(&adb->af6mp);	DESTROYLOCK(&adb->reflock); fail0d:	DESTROYLOCK(&adb->mplock); fail0c:	DESTROYLOCK(&adb->lock); fail0b:	isc_mem_put(mem, adb, sizeof (dns_adb_t));	return (result);}voiddns_adb_attach(dns_adb_t *adb, dns_adb_t **adbx) {	REQUIRE(DNS_ADB_VALID(adb));	REQUIRE(adbx != NULL && *adbx == NULL);	inc_adb_erefcnt(adb);	*adbx = adb;}voiddns_adb_detach(dns_adb_t **adbx) {	dns_adb_t *adb;	isc_boolean_t need_exit_check;	REQUIRE(adbx != NULL && DNS_ADB_VALID(*adbx));	adb = *adbx;	*adbx = NULL;	INSIST(adb->erefcnt > 0);	LOCK(&adb->reflock);	adb->erefcnt--;	need_exit_check = ISC_TF(adb->erefcnt == 0 && adb->irefcnt == 0);	UNLOCK(&adb->reflock);	if (need_exit_check) {		LOCK(&adb->lock);		INSIST(adb->shutting_down);		check_exit(adb);		UNLOCK(&adb->lock);	}}voiddns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) {	isc_task_t *clone;	isc_event_t *event;	isc_boolean_t zeroirefcnt = ISC_FALSE;	/*	 * Send '*eventp' to 'task' when 'adb' has shutdown.	 */	REQUIRE(DNS_ADB_VALID(adb));	REQUIRE(eventp != NULL);	event = *eventp;	*eventp = NULL;	LOCK(&adb->lock);	LOCK(&adb->reflock);	zeroirefcnt = ISC_TF(adb->irefcnt == 0);	if (adb->shutting_down && zeroirefcnt &&	    isc_mempool_getallocated(adb->ahmp) == 0) {		/*		 * We're already shutdown.  Send the event.		 */		event->ev_sender = adb;		isc_task_send(task, &event);	} else {		clone = NULL;		isc_task_attach(task, &clone);		event->ev_sender = clone;		ISC_LIST_APPEND(adb->whenshutdown, event, ev_link);	}	UNLOCK(&adb->reflock);	UNLOCK(&adb->lock);}voiddns_adb_shutdown(dns_adb_t *adb) {	isc_boolean_t need_check_exit;	/*	 * Shutdown 'adb'.	 */	LOCK(&adb->lock);	if (!adb->shutting_down) {		adb->shutting_down = ISC_TRUE;		need_check_exit = shutdown_names(adb);		if (!need_check_exit)			need_check_exit = shutdown_entries(adb);		if (need_check_exit)			check_exit(adb);	}	UNLOCK(&adb->lock);}isc_result_tdns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,		   void *arg, dns_name_t *name, dns_name_t *zone,		   unsigned int options, isc_stdtime_t now, dns_name_t *target,		   in_port_t port, dns_adbfind_t **findp){	dns_adbfind_t *find;	dns_adbname_t *adbname;	int bucket;	isc_boolean_t want_event, start_at_zone, alias, have_address;	isc_result_t result;	unsigned int wanted_addresses;	unsigned int wanted_fetches;	unsigned int query_pending;	REQUIRE(DNS_ADB_VALID(adb));	if (task != NULL) {		REQUIRE(action != NULL);	}	REQUIRE(name != NULL);	REQUIRE(zone != NULL);	REQUIRE(findp != NULL && *findp == NULL);	REQUIRE(target == NULL || dns_name_hasbuffer(target));	REQUIRE((options & DNS_ADBFIND_ADDRESSMASK) != 0);	result = ISC_R_UNEXPECTED;	wanted_addresses = (options & DNS_ADBFIND_ADDRESSMASK);	wanted_fetches = 0;	query_pending = 0;	want_event = ISC_FALSE;	start_at_zone = ISC_FALSE;	alias = ISC_FALSE;	if (now == 0)		isc_stdtime_get(&now);	/*	 * XXXMLG  Move this comment somewhere else!	 *	 * Look up the name in our internal database.	 *	 * Possibilities:  Note that these are not always exclusive.	 *	 *	No name found.  In this case, allocate a new name header and	 *	an initial namehook or two.  If any of these allocations	 *	fail, clean up and return ISC_R_NOMEMORY.	 *	 *	Name found, valid addresses present.  Allocate one addrinfo	 *	structure for each found and append it to the linked list	 *	of addresses for this header.	 *	 *	Name found, queries pending.  In this case, if a task was	 *	passed in, allocate a job id, attach it to the name's job	 *	list and remember to tell the caller that there will be	 *	more info coming later.	 */	find = new_adbfind(adb);	if (find == NULL)		return (ISC_R_NOMEMORY);	find->port = port;	/*	 * Remember what types of addresses we are interested in.	 */	find->options = options;	find->flags |= wanted_addresses;	if (FIND_WANTEVENT(find)) {		REQUIRE(task != NULL);	}	/*	 * Try to see if we know anything about this name at all.	 */	bucket = DNS_ADB_INVALIDBUCKET;	adbname = find_name_and_lock(adb, name, find->options, &bucket);	if (adb->name_sd[bucket]) {		DP(DEF_LEVEL,		   "dns_adb_createfind: returning ISC_R_SHUTTINGDOWN");		RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);		result = ISC_R_SHUTTINGDOWN;		goto out;	}	/*	 * Nothing found.  Allocate a new adbname structure for this name.	 */	if (adbname == NULL) {		adbname = new_adbname(adb, name);		if (adbname == NULL) {			RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);			result = ISC_R_NOMEMORY;			goto out;		}		link_name(adb, bucket, adbname);		if (FIND_HINTOK(find))			adbname->flags |= NAME_HINT_OK;		if (FIND_GLUEOK(find))			adbname->flags |= NAME_GLUE_OK;		if (FIND_STARTATZONE(find))			adbname->flags |= NAME_STARTATZONE;	}	/*	 * Expire old entries, etc.	 */	RUNTIME_CHECK(check_expire_namehook

⌨️ 快捷键说明

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