* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbt.c,v 1.115.2.2 2003/07/22 04:03:42 marka Exp $ */
+/* $Id: rbt.c,v 1.115.2.3 2004/03/03 22:38:20 marka Exp $ */
/* Principal Authors: DCL */
(name)->attributes |= DNS_NAMEATTR_READONLY; \
} while (0)
+#ifdef DNS_RBT_USEHASH
+static isc_result_t
+inithash(dns_rbt_t *rbt);
+#endif
+
#ifdef DEBUG
#define inline
/*
create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep);
#ifdef DNS_RBT_USEHASH
-static inline isc_result_t
+static inline void
hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
static inline void
unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
void *deleter_arg, dns_rbt_t **rbtp)
{
+#ifdef DNS_RBT_USEHASH
+ isc_result_t result;
+#endif
dns_rbt_t *rbt;
+
REQUIRE(mctx != NULL);
REQUIRE(rbtp != NULL && *rbtp == NULL);
rbt->nodecount = 0;
rbt->hashtable = NULL;
rbt->hashsize = 0;
+#ifdef DNS_RBT_USEHASH
+ result = inithash(rbt);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, rbt, sizeof(*rbt));
+ return (result);
+ }
+#endif
rbt->magic = RBT_MAGIC;
*rbtp = rbt;
new_current->is_root = 1;
rbt->root = new_current;
*nodep = new_current;
- result = hash_node(rbt, new_current);
+ hash_node(rbt, new_current);
}
return (result);
}
ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;
rbt->nodecount++;
- result = hash_node(rbt, new_current);
- if (result != ISC_R_SUCCESS)
- break;
+ hash_node(rbt, new_current);
if (common_labels ==
dns_name_countlabels(add_name) &&
dns_rbt_addonlevel(new_current, current, order, root);
rbt->nodecount++;
*nodep = new_current;
- result = hash_node(rbt, new_current);
- /*
- * XXXDCL Ugh. If hash_node failed, it was because
- * there is not enough memory. The node is now unfindable,
- * and ideally should be removed. This is kind of tricky,
- * and all hell is probably going to break loose throughout
- * the rest of the library because of the lack of memory,
- * so fixing up the tree as though no addition had been
- * made is skipped. (Actually, this hash_node failing is
- * not the only situation in this file where an unexpected
- * error can leave things in an incorrect state.)
- */
+ hash_node(rbt, new_current);
}
return (result);
return (ISC_R_SUCCESS);
}
-static isc_result_t
+static void
rehash(dns_rbt_t *rbt) {
unsigned int oldsize;
dns_rbtnode_t **oldtable;
unsigned int i;
oldsize = rbt->hashsize;
- rbt->hashsize *= 2;
oldtable = rbt->hashtable;
+ rbt->hashsize *= 2 + 1;
rbt->hashtable = isc_mem_get(rbt->mctx,
rbt->hashsize * sizeof(dns_rbtnode_t *));
- if (rbt->hashtable == NULL)
- return (ISC_R_NOMEMORY);
+ if (rbt->hashtable == NULL) {
+ rbt->hashtable = oldtable;
+ rbt->hashsize = oldsize;
+ return;
+ }
for (i = 0; i < rbt->hashsize; i++)
rbt->hashtable[i] = NULL;
node = oldtable[i];
}
}
-
- isc_mem_put(rbt->mctx, oldtable,
- rbt->hashsize * sizeof(dns_rbtnode_t *) / 2);
-
- return (ISC_R_SUCCESS);
+
+ isc_mem_put(rbt->mctx, oldtable, oldsize * sizeof(dns_rbtnode_t *));
}
-static inline isc_result_t
+static inline void
hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
- isc_result_t result = ISC_R_SUCCESS;
- if (rbt->hashtable == NULL)
- result = inithash(rbt);
- else if (rbt->nodecount >= rbt->hashsize)
- result = rehash(rbt);
-
- if (result == ISC_R_SUCCESS)
- hash_add_node(rbt, node);
+ if (rbt->nodecount >= rbt->hashsize)
+ rehash(rbt);
- return (result);
+ hash_add_node(rbt, node);
}
static inline void