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.
This commit is contained in:
+11
-6
@@ -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 <config.h>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'.
|
||||
*
|
||||
|
||||
+45
-17
@@ -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
|
||||
|
||||
+4
-3
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user