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

📄 rbt.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
				 * this is the only real use of chains in the				 * function.  It could be done instead with				 * a simple integer variable, but I am pressed				 * for time.				 */				if (chain.level_count ==				    (sizeof(chain.levels) /				     sizeof(*chain.levels))) {					result = ISC_R_NOSPACE;					break;				}				/*				 * Split the name into two parts, a prefix				 * which is the not-in-common parts of the				 * two names and a suffix that is the common				 * parts of them.				 */				dns_name_split(&current_name, common_labels,					       prefix, suffix);				result = create_node(rbt->mctx, suffix,						     &new_current);				if (result != ISC_R_SUCCESS)					break;				/*				 * Reproduce the tree attributes of the				 * current node.				 */				new_current->is_root = current->is_root;				PARENT(new_current)  = PARENT(current);				LEFT(new_current)    = LEFT(current);				RIGHT(new_current)   = RIGHT(current);				COLOR(new_current)   = COLOR(current);				/*				 * Fix pointers that were to the current node.				 */				if (parent != NULL) {					if (LEFT(parent) == current)						LEFT(parent) = new_current;					else						RIGHT(parent) = new_current;				}				if (LEFT(new_current) != NULL)					PARENT(LEFT(new_current)) =						new_current;				if (RIGHT(new_current) != NULL)					PARENT(RIGHT(new_current)) =						new_current;				if (*root == current)					*root = new_current;				NAMELEN(current) = prefix->length;				OFFSETLEN(current) = prefix->labels;				memcpy(OFFSETS(current), prefix->offsets,				       prefix->labels);				PADBYTES(current) +=				       (current_name.length - prefix->length) +				       (current_name.labels - prefix->labels);				/*				 * Set up the new root of the next level.				 * By definition it will not be the top				 * level tree, so clear DNS_NAMEATTR_ABSOLUTE.				 */				current->is_root = 1;				PARENT(current) = new_current;				DOWN(new_current) = current;				root = &DOWN(new_current);				ADD_LEVEL(&chain, new_current);				LEFT(current) = NULL;				RIGHT(current) = NULL;				MAKE_BLACK(current);				ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;				rbt->nodecount++;				hash_node(rbt, new_current);				if (common_labels ==				    dns_name_countlabels(add_name)) {					/*					 * The name has been added by pushing					 * the not-in-common parts down to					 * a new level.					 */					*nodep = new_current;					return (ISC_R_SUCCESS);				} else {					/*					 * The current node has no data,					 * because it is just a placeholder.					 * Its data pointer is already NULL					 * from create_node()), so there's					 * nothing more to do to it.					 */					/*					 * The not-in-common parts of the new					 * name will be inserted into the new					 * level following this loop (unless					 * result != ISC_R_SUCCESS, which					 * is tested after the loop ends).					 */					dns_name_split(add_name, common_labels,						       add_name, NULL);					break;				}			}		}	} while (child != NULL);	if (result == ISC_R_SUCCESS)		result = create_node(rbt->mctx, add_name, &new_current);	if (result == ISC_R_SUCCESS) {		dns_rbt_addonlevel(new_current, current, order, root);		rbt->nodecount++;		*nodep = new_current;		hash_node(rbt, new_current);	}	return (result);}/* * Add a name to the tree of trees, associating it with some data. */isc_result_tdns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data) {	isc_result_t result;	dns_rbtnode_t *node;	REQUIRE(VALID_RBT(rbt));	REQUIRE(dns_name_isabsolute(name));	node = NULL;	result = dns_rbt_addnode(rbt, name, &node);	/*	 * dns_rbt_addnode will report the node exists even when	 * it does not have data associated with it, but the	 * dns_rbt_*name functions all behave depending on whether	 * there is data associated with a node.	 */	if (result == ISC_R_SUCCESS ||	    (result == ISC_R_EXISTS && DATA(node) == NULL)) {		DATA(node) = data;		result = ISC_R_SUCCESS;	}	return (result);}/* * Find the node for "name" in the tree of trees. */isc_result_tdns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,		 dns_rbtnode_t **node, dns_rbtnodechain_t *chain,		 unsigned int options, dns_rbtfindcallback_t callback,		 void *callback_arg){	dns_rbtnode_t *current, *last_compared, *current_root;	dns_rbtnodechain_t localchain;	dns_name_t *search_name, current_name, *callback_name;	dns_fixedname_t fixedcallbackname, fixedsearchname;	dns_namereln_t compared;	isc_result_t result, saved_result;	unsigned int common_labels;	int order;	REQUIRE(VALID_RBT(rbt));	REQUIRE(dns_name_isabsolute(name));	REQUIRE(node != NULL && *node == NULL);	REQUIRE((options & (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR))		!=         (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR));	/*	 * If there is a chain it needs to appear to be in a sane state,	 * otherwise a chain is still needed to generate foundname and	 * callback_name.	 */	if (chain == NULL) {		options |= DNS_RBTFIND_NOPREDECESSOR;		chain = &localchain;		dns_rbtnodechain_init(chain, rbt->mctx);	} else		dns_rbtnodechain_reset(chain);	if (rbt->root == NULL)		return (ISC_R_NOTFOUND);	else {		/*		 * Appease GCC about variables it incorrectly thinks are		 * possibly used uninitialized.		 */		compared = dns_namereln_none;		last_compared = NULL;	}	dns_fixedname_init(&fixedcallbackname);	callback_name = dns_fixedname_name(&fixedcallbackname);	/*	 * search_name is the name segment being sought in each tree level.	 * By using a fixedname, the search_name will definitely have offsets	 * for use by any splitting.	 * By using dns_name_clone, no name data should be copied thanks to	 * the lack of bitstring labels.	 */	dns_fixedname_init(&fixedsearchname);	search_name = dns_fixedname_name(&fixedsearchname);	dns_name_clone(name, search_name);	dns_name_init(&current_name, NULL);	saved_result = ISC_R_SUCCESS;	current = rbt->root;	current_root = rbt->root;	while (current != NULL) {		NODENAME(current, &current_name);		compared = dns_name_fullcompare(search_name, &current_name,						&order, &common_labels);		last_compared = current;		if (compared == dns_namereln_equal)			break;		if (compared == dns_namereln_none) {#ifdef DNS_RBT_USEHASH			dns_name_t hash_name;			dns_rbtnode_t *hnode;			dns_rbtnode_t *up_current;			unsigned int nlabels;			unsigned int tlabels = 1;			unsigned int hash;			/*			 * If there is no hash table, hashing can't be done.			 */			if (rbt->hashtable == NULL)				goto nohash;			/*			 * The case of current != current_root, that			 * means a left or right pointer was followed,			 * only happens when the algorithm fell through to			 * the traditional binary search because of a			 * bitstring label.  Since we dropped the bitstring			 * support, this should not happen.			 */			INSIST(current == current_root);			nlabels = dns_name_countlabels(search_name);			/*			 * current_root is the root of the current level, so			 * it's parent is the same as it's "up" pointer.			 */			up_current = PARENT(current_root);			dns_name_init(&hash_name, NULL);		hashagain:			dns_name_getlabelsequence(search_name,						  nlabels - tlabels,						  tlabels, &hash_name);			hash = HASHVAL(up_current) +			       dns_name_hashbylabel(&hash_name, ISC_FALSE);			for (hnode = rbt->hashtable[hash % rbt->hashsize];			     hnode != NULL;			     hnode = hnode->hashnext)			{				dns_name_t hnode_name;				if (hash != HASHVAL(hnode))					continue;				if (find_up(hnode) != up_current)					continue;				dns_name_init(&hnode_name, NULL);				NODENAME(hnode, &hnode_name);				if (dns_name_equal(&hnode_name, &hash_name))					break;			}			if (hnode != NULL) {				current = hnode;				/*				 * This is an optimization.  If hashing found				 * the right node, the next call to				 * dns_name_fullcompare() would obviously				 * return _equal or _subdomain.  Determine				 * which of those would be the case by				 * checking if the full name was hashed.  Then				 * make it look like dns_name_fullcompare				 * was called and jump to the right place.				 */				if (tlabels == nlabels) {					compared = dns_namereln_equal;					break;				} else {					common_labels = tlabels;					compared = dns_namereln_subdomain;					goto subdomain;				}			}			if (tlabels++ < nlabels)				goto hashagain;			/*			 * All of the labels have been tried against the hash			 * table.  Since we dropped the support of bitstring			 * labels, the name isn't in the table.			 */			current = NULL;			continue;			    		nohash:#endif /* DNS_RBT_USEHASH */			/*			 * Standard binary search tree movement.			 */			if (order < 0)				current = LEFT(current);			else				current = RIGHT(current);		} else {			/*			 * The names have some common suffix labels.			 *			 * If the number in common are equal in length to			 * the current node's name length, then follow the			 * down pointer and search in the new tree.			 */			if (compared == dns_namereln_subdomain) {		subdomain:				/*				 * Whack off the current node's common parts				 * for the name to search in the next level.				 */				dns_name_split(search_name, common_labels,					       search_name, NULL);				/*				 * This might be the closest enclosing name.				 */				if (DATA(current) != NULL ||				    (options & DNS_RBTFIND_EMPTYDATA) != 0)					*node = current;				/*				 * Point the chain to the next level.   This				 * needs to be done before 'current' is pointed				 * there because the callback in the next				 * block of code needs the current 'current',				 * but in the event the callback requests that				 * the search be stopped then the				 * DNS_R_PARTIALMATCH code at the end of this				 * function needs the chain pointed to the				 * next level.				 */				ADD_LEVEL(chain, current);				/*				 * The caller may want to interrupt the				 * downward search when certain special nodes				 * are traversed.  If this is a special node,				 * the callback is used to learn what the				 * caller wants to do.				 */				if (callback != NULL &&				    FINDCALLBACK(current)) {					result = chain_name(chain,							    callback_name,							    ISC_FALSE);					if (result != ISC_R_SUCCESS) {						dns_rbtnodechain_reset(chain);						return (result);					}					result = (callback)(current,							    callback_name,							    callback_arg);					if (result != DNS_R_CONTINUE) {						saved_result = result;						/*						 * Treat this node as if it						 * had no down pointer.						 */						current = NULL;						break;					}				}				/*				 * Finally, head to the next tree level.				 */				current = DOWN(current);				current_root = current;			} else {				/*				 * Though there are labels in common, the				 * entire name at this node is not common				 * with the search name so the search				 * name does not exist in the tree.				 */				INSIST(compared == dns_namereln_commonancestor				       || compared == dns_namereln_contains);				current = NULL;			}		}	}	/*	 * If current is not NULL, NOEXACT is not disallowing exact matches,	 * and either the node has data or an empty node is ok, return	 * ISC_R_SUCCESS to indicate an exact match.	 */	if (current != NULL && (options & DNS_RBTFIND_NOEXACT) == 0 &&	    (DATA(current) != NULL ||	     (options & DNS_RBTFIND_EMPTYDATA) != 0)) {		/*		 * Found an exact match.		 */		chain->end = current;		chain->level_matches = chain->level_count;		if (foundname != NULL)			result = chain_name(chain, foundname, ISC_TRUE);		else			result = ISC_R_SUCCESS;		if (result == ISC_R_SUCCESS) {			*node = current;			result = saved_result;		} else			*node = NULL;	} else {		/*		 * Did not find an exact match (or did not want one).		 */		if (*node != NULL) {			/*			 * ... but found a partially matching superdomain.			 * Unwind the chain to the partial match node			 * to set level_matches to the level above the node,			 * and then to derive the name.			 *			 * chain->level_count is guaranteed to be at least 1			 * here because by definition of finding a superdomain,			 * the chain is pointed to at least the first subtree.			 */			chain->level_matches = chain->level_count - 1;			while (chain->levels[chain->level_matches] != *node) {				INSIST(chain->level_matches > 0);				chain->level_matches--;			}			if (foundname != NULL) {				unsigned int saved_count = chain->level_count;				chain->level_count = chain->level_matches + 1;				result = chain_name(chain, foundname,						    ISC_FALSE);				chain->level_count = saved_count;			} else				result = ISC_R_SUCCESS;			if (result == ISC_R_SUCCESS)				result = DNS_R_PARTIALMATCH;		} else			result = ISC_R_NOTFOUND;		if (current != NULL) {			/*			 * There was an exact match but either			 * DNS_RBTFIND_NOEXACT was set, or			 * DNS_RBTFIND_EMPTYDATA was set and the node had no			 * data.  A policy decision was made to set the			 * chain to the exact match, but this is subject			 * to change if it becomes apparent that something			 * else would be more useful.  It is important that			 * this case is handled here, because the predecessor			 * setting code below assumes the match was not exact.			 */			INSIST(((options & DNS_RBTFIND_NOEXACT) != 0) ||			       ((options & DNS_RBTFIND_EMPTYDATA) == 0 &&				DATA(current) == NULL));			chain->end = current;

⌨️ 快捷键说明

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