From 587fc7b519b0fed4e3dd234527edba1ca9334757 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Thu, 4 Mar 1999 21:03:29 +0000 Subject: [PATCH] Revised dns_rbt_findname and dns_rbt_findnode to find the closest match when an exact match cannot be found. This changed the calling interface, which necessitated changes to rbtdb.c and compress.c. --- lib/dns/compress.c | 17 +++++++---- lib/dns/include/dns/rbt.h | 15 +++++----- lib/dns/rbt.c | 62 ++++++++++++++++++++++++++++----------- lib/dns/rbtdb.c | 7 +++-- 4 files changed, 68 insertions(+), 33 deletions(-) diff --git a/lib/dns/compress.c b/lib/dns/compress.c index 54a4cede40..7eac42bac7 100644 --- a/lib/dns/compress.c +++ b/lib/dns/compress.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: compress.c,v 1.4 1999/02/26 00:25:12 marka Exp $ */ + /* $Id: compress.c,v 1.5 1999/03/04 21:03:29 tale Exp $ */ #include @@ -436,7 +436,6 @@ compress_find(dns_rbt_t *root, dns_name_t *name, dns_name_t *prefix, labels = count = dns_name_countlabels(name); start = 0; - data = NULL; bits = 0; dns_name_init(&tmpname, NULL); @@ -445,8 +444,12 @@ compress_find(dns_rbt_t *root, dns_name_t *name, dns_name_t *prefix, /* Don't look for the root label (count == 1). */ while (count > 1) { dns_name_getlabelsequence(name, start, count, &tmpname); - data = dns_rbt_findname(root, &tmpname); - if (data != NULL) + data = NULL; + result = dns_rbt_findname(root, &tmpname, (void *)&data); + /* XXX @@@ is this right, Mark? + note that for data to be non-null, then result can + be DNS_R_SUCCESS or DNS_R_PARTIALMATCH */ + if (result == DNS_R_SUCCESS && data != NULL) break; count--; start++; @@ -476,8 +479,10 @@ compress_find(dns_rbt_t *root, dns_name_t *name, dns_name_t *prefix, &tmpname, workspace); if (result != DNS_R_SUCCESS) continue; - data = dns_rbt_findname(root, &tmpname); - if (data != NULL) + data = NULL; + result = dns_rbt_findname(root, &tmpname, (void *)&data); + /* XXX @@@ is this right, Mark? */ + if (result == DNS_R_SUCCESS && data != NULL) break; if (bits == 1) bits = 0; diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h index b56fc94917..beda896906 100644 --- a/lib/dns/include/dns/rbt.h +++ b/lib/dns/include/dns/rbt.h @@ -42,10 +42,10 @@ typedef struct dns_rbt dns_rbt_t; #define DNS_RBT_LOCKLENGTH 11 #define DNS_RBT_REFLENGTH 20 -typedef struct dns_rbt_node { - struct dns_rbt_node *left; - struct dns_rbt_node *right; - struct dns_rbt_node *down; +typedef struct dns_rbtnode { + struct dns_rbtnode *left; + struct dns_rbtnode *right; + struct dns_rbtnode *down; /* * We'd like to find a better place for the single bit of color * information. We can't pack it into the bitfield below, however, @@ -138,8 +138,9 @@ void dns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name); * */ -dns_rbtnode_t *dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, - dns_rbtnodechain_t *chain); +dns_result_t dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, + dns_rbtnode_t **node, + dns_rbtnodechain_t *chain); /* * Find the node for 'name'. * @@ -148,7 +149,7 @@ dns_rbtnode_t *dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, * has a non-NULL data pointer. */ -void *dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name); +dns_result_t dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, void **data); /* * Return the data pointer associated with 'name'. * diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index 876fe00f06..15c36665ba 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -240,8 +240,9 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) { dns_result_t result; dns_rbtnodechain_t chain; isc_region_t r; - int add_labels, current_labels, keep_labels, start_label, order; + unsigned int add_labels, current_labels, keep_labels, start_label; unsigned int common_labels, common_bits; + int order; REQUIRE(VALID_RBT(rbt)); REQUIRE(FAST_ISABSOLUTE(name)); @@ -315,6 +316,8 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) { } } else { + /* @@@ handle bitstrings */ + /* * This name has some suffix in common with the * name at the current node. If the name at @@ -538,21 +541,25 @@ dns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data) { * If second argument "up" is non-NULL, set it to the node that has * the down pointer for the found node. */ -dns_rbtnode_t * -dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnodechain_t *chain) { +dns_result_t +dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **node, + dns_rbtnodechain_t *chain) +{ dns_rbtnode_t *current; dns_name_t *search_name, *new_search_name, *current_name; dns_name_t holder1, holder2; dns_namereln_t compared; + dns_result_t result; dns_offsets_t holder1_offsets, holder2_offsets; - int current_labels, keep_labels, order; - unsigned int common_labels, common_bits; isc_region_t r; + unsigned int current_labels, keep_labels, common_labels, common_bits; + int order; /* @@@ optimize skipping the root node? */ REQUIRE(VALID_RBT(rbt)); REQUIRE(FAST_ISABSOLUTE(name)); + REQUIRE(node != NULL && *node == NULL); dns_name_init(&holder1, holder1_offsets); dns_name_init(&holder2, holder2_offsets); @@ -576,7 +583,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnodechain_t *chain) { chain->level_count = 0; if (get_ancestor_mem(rbt->mctx, chain) != DNS_R_SUCCESS) - return (NULL); + return (DNS_R_NOMEMORY); ADD_ANCESTOR(chain, NULL); } @@ -596,7 +603,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnodechain_t *chain) { if (chain != NULL && chain->ancestor_count == chain->ancestor_maxitems && get_ancestor_mem(rbt->mctx, chain) != DNS_R_SUCCESS) - return (NULL); + return (DNS_R_NOMEMORY); /* * Standard binary search tree movement. @@ -654,36 +661,55 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnodechain_t *chain) { ADD_LEVEL(chain, current); } + /* + * This might be the closest enclosing name. + */ + *node = current; + /* * Search in the next tree level. */ current = DOWN(current); - } else + } else { /* * Though there is a suffix in common, it * has no down pointer, so the name does * not exist. */ current = NULL; + } } } - return (current); + if (current != NULL) { + *node = current; + result = DNS_R_SUCCESS; + } else if (*node != NULL) { + result = DNS_R_PARTIALMATCH; + } else { + result = DNS_R_NOTFOUND; + } + + return (result); } -void * -dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name) { - dns_rbtnode_t *node; +dns_result_t +dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, void **data) { + dns_rbtnode_t *node = NULL; + dns_result_t result; REQUIRE(VALID_RBT(rbt)); + REQUIRE(data != NULL && *data == NULL); - node = dns_rbt_findnode(rbt, name, NULL); + result = dns_rbt_findnode(rbt, name, &node, NULL); if (node != NULL && DATA(node) != NULL) - return(DATA(node)); + *data = DATA(node); else - return(NULL); + result = DNS_R_NOTFOUND; + + return (result); } /* @@ -691,7 +717,7 @@ dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name) { */ dns_result_t dns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, isc_boolean_t recurse) { - dns_rbtnode_t *node; + dns_rbtnode_t *node = NULL; dns_result_t result; dns_rbtnodechain_t chain; @@ -711,8 +737,10 @@ dns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, isc_boolean_t recurse) { * * @@@ how to ->dirty, ->locknum and ->references figure in? */ + result = dns_rbt_findnode(rbt, name, &node, &chain); - node = dns_rbt_findnode(rbt, name, &chain); + if (result != DNS_R_SUCCESS) + return (DNS_R_NOTFOUND); /* * The guts of this routine are in a separate function (which diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 236d8425a3..fc5ff278d9 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -669,7 +669,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { static dns_result_t findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, - dns_dbnode_t **nodep) { + dns_dbnode_t **nodep) +{ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; dns_rbtnode_t *node = NULL; dns_name_t foundname; @@ -681,9 +682,9 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, dns_name_init(&foundname, NULL); RWLOCK(&rbtdb->tree_lock, locktype); - node = dns_rbt_findnode(rbtdb->tree, name, NULL); + result = dns_rbt_findnode(rbtdb->tree, name, &node, NULL); again: - if (node != NULL) { + if (result == DNS_R_SUCCESS) { locknum = node->locknum; LOCK(&rbtdb->node_locks[locknum].lock); if (node->references == 0)