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

📄 rbtdb.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (!changed->dirty) {			UNLINK(version->changed_list,			       changed, link);			APPEND(*cleanup_list,			       changed, link);		}	}}static voidcloseversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {	dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;	rbtdb_version_t *version, *cleanup_version, *least_greater;	isc_boolean_t rollback = ISC_FALSE;	rbtdb_changedlist_t cleanup_list;	rbtdb_changed_t *changed, *next_changed;	rbtdb_serial_t serial, least_serial;	dns_rbtnode_t *rbtnode;	isc_mutex_t *lock;	REQUIRE(VALID_RBTDB(rbtdb));	version = (rbtdb_version_t *)*versionp;	cleanup_version = NULL;	ISC_LIST_INIT(cleanup_list);	LOCK(&rbtdb->lock);	INSIST(version->references > 0);	INSIST(!version->writer || !(commit && version->references > 1));	version->references--;	serial = version->serial;	if (version->references == 0) {		if (version->writer) {			if (commit) {				INSIST(version->commit_ok);				INSIST(version == rbtdb->future_version);				if (EMPTY(rbtdb->open_versions)) {					/*					 * We're going to become the least open					 * version.					 */					make_least_version(rbtdb, version,							   &cleanup_list);				} else {					/*					 * Some other open version is the					 * least version.  We can't cleanup					 * records that were changed in this					 * version because the older versions					 * may still be in use by an open					 * version.					 *					 * We can, however, discard the					 * changed records for things that					 * we've added that didn't exist in					 * prior versions.					 */					cleanup_nondirty(version,							 &cleanup_list);				}				/*				 * If the (soon to be former) current version				 * isn't being used by anyone, we can clean				 * it up.				 */				if (rbtdb->current_version->references == 0) {					cleanup_version =						rbtdb->current_version;					APPENDLIST(version->changed_list,						 cleanup_version->changed_list,						   link);				}				/*				 * Become the current version.				 */				version->writer = ISC_FALSE;				rbtdb->current_version = version;				rbtdb->current_serial = version->serial;				rbtdb->future_version = NULL;			} else {				/*				 * We're rolling back this transaction.				 */				cleanup_list = version->changed_list;				ISC_LIST_INIT(version->changed_list);				rollback = ISC_TRUE;				cleanup_version = version;				rbtdb->future_version = NULL;			}		} else {			if (version != rbtdb->current_version) {				/*				 * There are no external or internal references				 * to this version and it can be cleaned up.				 */				cleanup_version = version;				/*				 * Find the version with the least serial				 * number greater than ours.				 */				least_greater = PREV(version, link);				if (least_greater == NULL)					least_greater = rbtdb->current_version;				INSIST(version->serial < least_greater->serial);				/*				 * Is this the least open version?				 */				if (version->serial == rbtdb->least_serial) {					/*					 * Yes.  Install the new least open					 * version.					 */					make_least_version(rbtdb,							   least_greater,							   &cleanup_list);				} else {					/*					 * Add any unexecuted cleanups to					 * those of the least greater version.					 */					APPENDLIST(least_greater->changed_list,						   version->changed_list,						   link);				}			} else if (version->serial == rbtdb->least_serial)				INSIST(EMPTY(version->changed_list));			UNLINK(rbtdb->open_versions, version, link);		}	}	least_serial = rbtdb->least_serial;	UNLOCK(&rbtdb->lock);	if (cleanup_version != NULL) {		INSIST(EMPTY(cleanup_version->changed_list));		isc_mem_put(rbtdb->common.mctx, cleanup_version,			    sizeof(*cleanup_version));	}	if (!EMPTY(cleanup_list)) {		for (changed = HEAD(cleanup_list);		     changed != NULL;		     changed = next_changed) {			next_changed = NEXT(changed, link);			rbtnode = changed->node;			lock = &rbtdb->node_locks[rbtnode->locknum].lock;			LOCK(lock);			INSIST(rbtnode->references > 0);			rbtnode->references--;			if (rollback)				rollback_node(rbtnode, serial);			if (rbtnode->references == 0)				no_references(rbtdb, rbtnode, least_serial,					      isc_rwlocktype_none);			UNLOCK(lock);			isc_mem_put(rbtdb->common.mctx, changed,				    sizeof(*changed));		}	}	*versionp = NULL;}/* * Add the necessary magic for the wildcard name 'name' * to be found in 'rbtdb'. * * In order for wildcard matching to work correctly in * zone_find(), we must ensure that a node for the wildcarding * level exists in the database, and has its 'find_callback' * and 'wild' bits set. * * E.g. if the wildcard name is "*.sub.example." then we * must ensure that "sub.example." exists and is marked as * a wildcard level. */static isc_result_tadd_wildcard_magic(dns_rbtdb_t *rbtdb, dns_name_t *name) {	isc_result_t result;	dns_name_t foundname;	dns_offsets_t offsets;	unsigned int n;	dns_rbtnode_t *node = NULL;	dns_name_init(&foundname, offsets);	n = dns_name_countlabels(name);	INSIST(n >= 2);	n--;	dns_name_getlabelsequence(name, 1, n, &foundname);	result = dns_rbt_addnode(rbtdb->tree, &foundname, &node);	if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)		return (result);	node->find_callback = 1;	node->wild = 1;	return (ISC_R_SUCCESS);}static isc_result_tadd_empty_wildcards(dns_rbtdb_t *rbtdb, dns_name_t *name) {	isc_result_t result;	dns_name_t foundname;	dns_offsets_t offsets;	unsigned int n, l, i;	dns_name_init(&foundname, offsets);	n = dns_name_countlabels(name);	l = dns_name_countlabels(&rbtdb->common.origin);	i = l + 1;	while (i < n) {		dns_rbtnode_t *node = NULL;	/* dummy */		dns_name_getlabelsequence(name, n - i, i, &foundname);		if (dns_name_iswildcard(&foundname)) {			result = add_wildcard_magic(rbtdb, &foundname);			if (result != ISC_R_SUCCESS)				return (result);			result = dns_rbt_addnode(rbtdb->tree, &foundname,						 &node);			if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)				return (result);		}		i++;	}	return (ISC_R_SUCCESS);}static isc_result_tfindnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,	 dns_dbnode_t **nodep){	dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;	dns_rbtnode_t *node = NULL;	dns_name_t nodename;	unsigned int locknum;	isc_result_t result;	isc_rwlocktype_t locktype = isc_rwlocktype_read;	REQUIRE(VALID_RBTDB(rbtdb));	dns_name_init(&nodename, NULL);	RWLOCK(&rbtdb->tree_lock, locktype);	result = dns_rbt_findnode(rbtdb->tree, name, NULL, &node, NULL,				  DNS_RBTFIND_EMPTYDATA, NULL, NULL);	if (result != ISC_R_SUCCESS) {		RWUNLOCK(&rbtdb->tree_lock, locktype);		if (!create) {			if (result == DNS_R_PARTIALMATCH)				result = ISC_R_NOTFOUND;			return (result);		}		/*		 * It would be nice to try to upgrade the lock instead of		 * unlocking then relocking.		 */		locktype = isc_rwlocktype_write;		RWLOCK(&rbtdb->tree_lock, locktype);		node = NULL;		result = dns_rbt_addnode(rbtdb->tree, name, &node);		if (result == ISC_R_SUCCESS) {			dns_rbt_namefromnode(node, &nodename);#ifdef DNS_RBT_USEHASH			node->locknum = node->hashval % rbtdb->node_lock_count;#else			node->locknum = dns_name_hash(&nodename, ISC_TRUE) %				rbtdb->node_lock_count;#endif			add_empty_wildcards(rbtdb, name);			if (dns_name_iswildcard(name)) {				result = add_wildcard_magic(rbtdb, name);				if (result != ISC_R_SUCCESS) {					RWUNLOCK(&rbtdb->tree_lock, locktype);					return (result);				}			}		} else if (result != ISC_R_EXISTS) {			RWUNLOCK(&rbtdb->tree_lock, locktype);			return (result);		}	}	locknum = node->locknum;	LOCK(&rbtdb->node_locks[locknum].lock);	new_reference(rbtdb, node);	UNLOCK(&rbtdb->node_locks[locknum].lock);	RWUNLOCK(&rbtdb->tree_lock, locktype);	*nodep = (dns_dbnode_t *)node;	return (ISC_R_SUCCESS);}static isc_result_tzone_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {	rbtdb_search_t *search = arg;	rdatasetheader_t *header, *header_next;	rdatasetheader_t *dname_header, *sigdname_header, *ns_header;	rdatasetheader_t *found;	isc_result_t result;	dns_rbtnode_t *onode;	/*	 * We only want to remember the topmost zone cut, since it's the one	 * that counts, so we'll just continue if we've already found a	 * zonecut.	 */	if (search->zonecut != NULL)		return (DNS_R_CONTINUE);	found = NULL;	result = DNS_R_CONTINUE;	onode = search->rbtdb->origin_node;	LOCK(&(search->rbtdb->node_locks[node->locknum].lock));	/*	 * Look for an NS or DNAME rdataset active in our version.	 */	ns_header = NULL;	dname_header = NULL;	sigdname_header = NULL;	for (header = node->data; header != NULL; header = header_next) {		header_next = header->next;		if (header->type == dns_rdatatype_ns ||		    header->type == dns_rdatatype_dname ||		    header->type == RBTDB_RDATATYPE_SIGDNAME) {			do {				if (header->serial <= search->serial &&				    !IGNORE(header)) {					/*					 * Is this a "this rdataset doesn't					 * exist" record?					 */					if (NONEXISTENT(header))						header = NULL;					break;				} else					header = header->down;			} while (header != NULL);			if (header != NULL) {				if (header->type == dns_rdatatype_dname)					dname_header = header;				else if (header->type == 					   RBTDB_RDATATYPE_SIGDNAME)					sigdname_header = header;				else if (node != onode ||					 IS_STUB(search->rbtdb)) {					/*					 * We've found an NS rdataset that					 * isn't at the origin node.  We check					 * that they're not at the origin node,					 * because otherwise we'd erroneously					 * treat the zone top as if it were					 * a delegation.					 */					ns_header = header;				}			}		}	}	/*	 * Did we find anything?	 */	if (dname_header != NULL) {		/*		 * Note that DNAME has precedence over NS if both exist.		 */		found = dname_header;		search->zonecut_sigrdataset = sigdname_header;	} else if (ns_header != NULL) {		found = ns_header;		search->zonecut_sigrdataset = NULL;	}	if (found != NULL) {		/*		 * We increment the reference count on node to ensure that		 * search->zonecut_rdataset will still be valid later.		 */		new_reference(search->rbtdb, node);		search->zonecut = node;		search->zonecut_rdataset = found;		search->need_cleanup = ISC_TRUE;		/*		 * Since we've found a zonecut, anything beneath it is		 * glue and is not subject to wildcard matching, so we		 * may clear search->wild.		 */		search->wild = ISC_FALSE;		if ((search->options & DNS_DBFIND_GLUEOK) == 0) {			/*			 * If the caller does not want to find glue, then			 * this is the best answer and the search should			 * stop now.			 */			result = DNS_R_PARTIALMATCH;		} else {			dns_name_t *zcname;			/*			 * The search will continue beneath the zone cut.			 * This may or may not be the best match.  In case it			 * is, we need to remember the node name.			 */			zcname = dns_fixedname_name(&search->zonecut_name);			RUNTIME_CHECK(dns_name_copy(name, zcname, NULL) ==				      ISC_R_SUCCESS);			search->copy_name = ISC_TRUE;		}	} else {		/*		 * There is no zonecut at this node which is active in this		 * version.		 *		 * If this is a "wild" node and the caller hasn't disabled		 * wildcard matching, remember that we've seen a wild node		 * in case we need to go searching for wildcard matches		 * later on.		 */		if (node->wild && (search->options & DNS_DBFIND_NOWILD) == 0)			search->wild = ISC_TRUE;	}	UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock));	return (result);}static inline voidbind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,	      rdatasetheader_t *header, isc_stdtime_t now,	      dns_rdataset_t *rdataset){	unsigned char *raw;	/*	 * Caller must be holding the node lock.	 */	if (rdataset == NULL)		return;	new_reference(rbtdb, node);	INSIST(rdataset->methods == NULL);	/* We must be disassociated. */	rdataset->methods = &rdataset_methods;	rdataset->rdclass = rbtdb->common.rdclass;	rdataset->type = RBTDB_RDATATYPE_BASE(header->type);	rdataset->covers = RBTDB_RDATATYPE_EXT(header->type);	rdataset->ttl = header->ttl - now;	rdataset->trust = header->trust;	if (NXDOMAIN(header))		rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;	rdataset->private1 = rbtdb;	rdataset->private2 = node;	raw = (unsigned char *)header + sizeof(*header);	rdataset->private3 = raw;	rdataset->count = header->count++;	if (header->count == ISC_UINT32_MAX)		header->count = 0;	/*	 * Reset iterator state.	 */	rdataset->privateuint4 = 0;	rdataset->private5 = NULL;	/*	 * Add noqname proof.	 */	rdataset->private6 = header->noqname;	if (rdataset->private6 != NULL)		rdataset->attributes |=  DNS_RDATASETATTR_NOQNAME;}static inline isc_result_tsetup_delegation(rbtdb_search_t *search, dns_dbnode_t **nodep,		 dns_name_t *foundname, dns_rdataset_t *rdataset,		 dns_rdataset_t *sigrdataset){	isc_result_t result;	dns_name_t *zcname;	rbtdb_rdatatype_t type;	dns_rbtnode_t *node;	/*	 * The caller MUST NOT be holding any node locks.	 */	node = search->zonecut;	type = search->zonecut_rdataset->type;	/*

⌨️ 快捷键说明

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