Commit 40e7c805 authored by Mark Andrews's avatar Mark Andrews
Browse files

1740. [bug] Replace rbt's hash algorithm as it performed badly

                        with certain zones. [RT #12729]
parent a79348a6
......@@ -36,7 +36,12 @@
1741. [bug] Deleting all records at a node in a secure zone
using a update-policy grant failed. [RT #12787]
1740. [placeholder] rt12729
1740. [bug] Replace rbt's hash algorithm as it performed badly
with certain zones. [RT #12729]
NOTE: a hash context now needs to be established
via isc_hash_create() if the application was not
already doing this.
1739. [bug] dns_rbt_deletetree() could incorrectly return
ISC_R_QUOTA. [RT #12695]
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named-checkzone.c,v 1.30 2004/10/06 05:56:28 marka Exp $ */
/* $Id: named-checkzone.c,v 1.31 2004/10/25 01:27:53 marka Exp $ */
#include <config.h>
......@@ -24,6 +24,8 @@
#include <isc/app.h>
#include <isc/commandline.h>
#include <isc/dir.h>
#include <isc/entropy.h>
#include <isc/hash.h>
#include <isc/log.h>
#include <isc/mem.h>
#include <isc/socket.h>
......@@ -44,6 +46,7 @@
static int quiet = 0;
static isc_mem_t *mctx = NULL;
static isc_entropy_t *ectx = NULL;
dns_zone_t *zone = NULL;
dns_zonetype_t zonetype = dns_zone_master;
static int dumpzone = 0;
......@@ -185,6 +188,9 @@ main(int argc, char **argv) {
dns_log_init(lctx);
dns_log_setcontext(lctx);
}
RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
== ISC_R_SUCCESS);
dns_result_register();
......@@ -201,6 +207,8 @@ main(int argc, char **argv) {
destroy();
if (lctx != NULL)
isc_log_destroy(&lctx);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return ((result == ISC_R_SUCCESS) ? 0 : 1);
}
......@@ -16,7 +16,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: dnssec-signzone.c,v 1.182 2004/08/28 06:16:51 marka Exp $ */
/* $Id: dnssec-signzone.c,v 1.183 2004/10/25 01:27:53 marka Exp $ */
#include <config.h>
......@@ -28,6 +28,7 @@
#include <isc/entropy.h>
#include <isc/event.h>
#include <isc/file.h>
#include <isc/hash.h>
#include <isc/mem.h>
#include <isc/mutex.h>
#include <isc/os.h>
......@@ -1824,6 +1825,11 @@ main(int argc, char *argv[]) {
eflags = ISC_ENTROPY_BLOCKING;
if (!pseudorandom)
eflags |= ISC_ENTROPY_GOODONLY;
result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (result != ISC_R_SUCCESS)
fatal("could not create hash context");
result = dst_lib_init(mctx, ectx, eflags);
if (result != ISC_R_SUCCESS)
fatal("could not initialize dst");
......@@ -2086,6 +2092,7 @@ main(int argc, char *argv[]) {
cleanup_logging(&log);
dst_lib_destroy();
isc_hash_destroy();
cleanup_entropy(&ectx);
if (verbose > 10)
isc_mem_stats(mctx, stdout);
......
This diff is collapsed.
......@@ -15,14 +15,17 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: t_rbt.c,v 1.25 2004/03/05 04:59:03 marka Exp $ */
/* $Id: t_rbt.c,v 1.26 2004/10/25 01:27:54 marka Exp $ */
#include <config.h>
#include <ctype.h>
#include <stdlib.h>
#include <isc/entropy.h>
#include <isc/mem.h>
#include <isc/util.h>
#include <isc/hash.h>
#include <isc/string.h>
#include <dns/fixedname.h>
......@@ -308,6 +311,7 @@ test_rbt_gen(char *filename, char *command, char *testname,
isc_result_t isc_result;
isc_result_t dns_result;
isc_mem_t *mctx;
isc_entropy_t *ectx;
dns_name_t *dns_name;
result = T_UNRESOLVED;
......@@ -316,6 +320,8 @@ test_rbt_gen(char *filename, char *command, char *testname,
t_info("testing using name %s\n", testname);
mctx = NULL;
ectx = NULL;
isc_result = isc_mem_create(0, 0, &mctx);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mem_create: %s: exiting\n",
......@@ -323,10 +329,29 @@ test_rbt_gen(char *filename, char *command, char *testname,
return(T_UNRESOLVED);
}
isc_result = isc_entropy_create(mctx, &ectx);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_entropy_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_hash_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
rbt = NULL;
if (rbt_init(filename, &rbt, mctx) != 0) {
if (strcmp(command, "create") == 0)
result = T_FAIL;
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
}
......@@ -412,6 +437,8 @@ test_rbt_gen(char *filename, char *command, char *testname,
}
dns_rbt_destroy(&rbt);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
}
......@@ -733,6 +760,7 @@ t_dns_rbtnodechain_init(char *dbfile, char *findname,
dns_rbtnode_t *node;
dns_rbtnodechain_t chain;
isc_mem_t *mctx;
isc_entropy_t *ectx;
isc_result_t isc_result;
isc_result_t dns_result;
dns_fixedname_t dns_findname;
......@@ -748,6 +776,8 @@ t_dns_rbtnodechain_init(char *dbfile, char *findname,
nfails = 0;
mctx = NULL;
ectx = NULL;
isc_result = isc_mem_create(0, 0, &mctx);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mem_create failed %s\n",
......@@ -755,11 +785,30 @@ t_dns_rbtnodechain_init(char *dbfile, char *findname,
return(result);
}
isc_result = isc_entropy_create(mctx, &ectx);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_entropy_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_hash_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
dns_rbtnodechain_init(&chain, mctx);
rbt = NULL;
if (rbt_init(dbfile, &rbt, mctx)) {
t_info("rbt_init %s failed\n", dbfile);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
}
......@@ -897,6 +946,8 @@ t_dns_rbtnodechain_init(char *dbfile, char *findname,
dns_rbtnodechain_invalidate(&chain);
dns_rbt_destroy(&rbt);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
......@@ -991,6 +1042,7 @@ t_dns_rbtnodechain_first(char *dbfile, char *expected_firstname,
dns_rbt_t *rbt;
dns_rbtnodechain_t chain;
isc_mem_t *mctx;
isc_entropy_t *ectx;
isc_result_t isc_result;
isc_result_t dns_result;
dns_fixedname_t dns_name;
......@@ -1001,6 +1053,7 @@ t_dns_rbtnodechain_first(char *dbfile, char *expected_firstname,
nfails = 0;
mctx = NULL;
ectx = NULL;
dns_fixedname_init(&dns_name);
dns_fixedname_init(&dns_origin);
......@@ -1012,11 +1065,30 @@ t_dns_rbtnodechain_first(char *dbfile, char *expected_firstname,
return(result);
}
isc_result = isc_entropy_create(mctx, &ectx);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_entropy_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_hash_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
dns_rbtnodechain_init(&chain, mctx);
rbt = NULL;
if (rbt_init(dbfile, &rbt, mctx)) {
t_info("rbt_init %s failed\n", dbfile);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
}
......@@ -1062,6 +1134,8 @@ t_dns_rbtnodechain_first(char *dbfile, char *expected_firstname,
dns_rbtnodechain_invalidate(&chain);
dns_rbt_destroy(&rbt);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
}
......@@ -1157,6 +1231,7 @@ t_dns_rbtnodechain_last(char *dbfile, char *expected_lastname,
dns_rbt_t *rbt;
dns_rbtnodechain_t chain;
isc_mem_t *mctx;
isc_entropy_t *ectx;
isc_result_t isc_result;
isc_result_t dns_result;
dns_fixedname_t dns_name;
......@@ -1167,6 +1242,7 @@ t_dns_rbtnodechain_last(char *dbfile, char *expected_lastname,
nfails = 0;
mctx = NULL;
ectx = NULL;
dns_fixedname_init(&dns_name);
dns_fixedname_init(&dns_origin);
......@@ -1178,11 +1254,30 @@ t_dns_rbtnodechain_last(char *dbfile, char *expected_lastname,
return(result);
}
isc_result = isc_entropy_create(mctx, &ectx);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_entropy_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_hash_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
dns_rbtnodechain_init(&chain, mctx);
rbt = NULL;
if (rbt_init(dbfile, &rbt, mctx)) {
t_info("rbt_init %s failed\n", dbfile);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
}
......@@ -1229,6 +1324,8 @@ t_dns_rbtnodechain_last(char *dbfile, char *expected_lastname,
dns_rbtnodechain_invalidate(&chain);
dns_rbt_destroy(&rbt);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
......@@ -1325,6 +1422,7 @@ t_dns_rbtnodechain_next(char *dbfile, char *findname,
dns_rbtnode_t *node;
dns_rbtnodechain_t chain;
isc_mem_t *mctx;
isc_entropy_t *ectx;
isc_result_t isc_result;
isc_result_t dns_result;
dns_fixedname_t dns_findname;
......@@ -1337,6 +1435,8 @@ t_dns_rbtnodechain_next(char *dbfile, char *findname,
nfails = 0;
mctx = NULL;
ectx = NULL;
isc_result = isc_mem_create(0, 0, &mctx);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mem_create failed %s\n",
......@@ -1344,11 +1444,30 @@ t_dns_rbtnodechain_next(char *dbfile, char *findname,
return(result);
}
isc_result = isc_entropy_create(mctx, &ectx);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_entropy_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_hash_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
dns_rbtnodechain_init(&chain, mctx);
rbt = NULL;
if (rbt_init(dbfile, &rbt, mctx)) {
t_info("rbt_init %s failed\n", dbfile);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
}
......@@ -1411,6 +1530,8 @@ t_dns_rbtnodechain_next(char *dbfile, char *findname,
dns_rbtnodechain_invalidate(&chain);
dns_rbt_destroy(&rbt);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
......@@ -1506,6 +1627,7 @@ t_dns_rbtnodechain_prev(char *dbfile, char *findname, char *prevname,
dns_rbtnode_t *node;
dns_rbtnodechain_t chain;
isc_mem_t *mctx;
isc_entropy_t *ectx = NULL;
isc_result_t isc_result;
isc_result_t dns_result;
dns_fixedname_t dns_findname;
......@@ -1518,6 +1640,8 @@ t_dns_rbtnodechain_prev(char *dbfile, char *findname, char *prevname,
nfails = 0;
mctx = NULL;
ectx = NULL;
isc_result = isc_mem_create(0, 0, &mctx);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mem_create failed %s\n",
......@@ -1525,11 +1649,30 @@ t_dns_rbtnodechain_prev(char *dbfile, char *findname, char *prevname,
return(result);
}
isc_result = isc_entropy_create(mctx, &ectx);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_entropy_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_hash_create: %s: exiting\n",
dns_result_totext(isc_result));
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(T_UNRESOLVED);
}
dns_rbtnodechain_init(&chain, mctx);
rbt = NULL;
if (rbt_init(dbfile, &rbt, mctx)) {
t_info("rbt_init %s failed\n", dbfile);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
}
......@@ -1592,6 +1735,8 @@ t_dns_rbtnodechain_prev(char *dbfile, char *findname, char *prevname,
dns_rbtnodechain_invalidate(&chain);
dns_rbt_destroy(&rbt);
isc_hash_destroy();
isc_entropy_detach(&ectx);
isc_mem_destroy(&mctx);
return(result);
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rbt.c,v 1.129 2004/10/11 05:49:28 marka Exp $ */
/* $Id: rbt.c,v 1.130 2004/10/25 01:27:54 marka Exp $ */
/* Principal Authors: DCL */
......@@ -64,7 +64,6 @@ struct dns_rbt {
unsigned int nodecount;
unsigned int hashsize;
dns_rbtnode_t ** hashtable;
unsigned int quantum;
};
#define RED 0
......@@ -180,25 +179,6 @@ find_up(dns_rbtnode_t *node) {
return (PARENT(root));
}
#ifdef DNS_RBT_USEHASH
static inline void
compute_node_hash(dns_rbtnode_t *node) {
unsigned int hash;
dns_name_t name;
dns_rbtnode_t *up_node;
dns_name_init(&name, NULL);
NODENAME(node, &name);
hash = dns_name_hashbylabel(&name, ISC_FALSE);
up_node = find_up(node);
if (up_node != NULL)
hash += HASHVAL(up_node);
HASHVAL(node) = hash;
}
#endif
/*
* Forward declarations.
*/
......@@ -207,11 +187,11 @@ create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep);
#ifdef DNS_RBT_USEHASH
static inline void
hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name);
static inline void
unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
#else
#define hash_node(rbt, node) (ISC_R_SUCCESS)
#define hash_node(rbt, node, name) (ISC_R_SUCCESS)
#define unhash_node(rbt, node)
#endif
......@@ -231,7 +211,8 @@ static isc_result_t
dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node);
static void
dns_rbt_deletetreeflat(dns_rbt_t *rbt, dns_rbtnode_t **nodep);
dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum,
dns_rbtnode_t **nodep);
/*
* Initialize a red/black tree of trees.
......@@ -268,7 +249,6 @@ dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
return (result);
}
#endif
rbt->quantum = 0;
rbt->magic = RBT_MAGIC;
*rbtp = rbt;
......@@ -292,9 +272,7 @@ dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
rbt = *rbtp;
rbt->quantum = quantum;
dns_rbt_deletetreeflat(rbt, &rbt->root);
dns_rbt_deletetreeflat(rbt, quantum, &rbt->root);
if (rbt->root != NULL)
return (ISC_R_QUOTA);
......@@ -377,13 +355,14 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
* Does this thing have too many variables or what?
*/
dns_rbtnode_t **root, *parent, *child, *current, *new_current;
dns_name_t *add_name, current_name, *prefix, *suffix;
dns_fixedname_t fixedcopy, fixedprefix, fixedsuffix;
dns_name_t *add_name, *new_name, current_name, *prefix, *suffix;
dns_fixedname_t fixedcopy, fixedprefix, fixedsuffix, fnewname;
dns_offsets_t current_offsets;
dns_namereln_t compared;
isc_result_t result = ISC_R_SUCCESS;
dns_rbtnodechain_t chain;
unsigned int common_labels;
unsigned int nlabels, hlabels;
int order;
REQUIRE(VALID_RBT(rbt));
......@@ -405,7 +384,7 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
new_current->is_root = 1;
rbt->root = new_current;
*nodep = new_current;
hash_node(rbt, new_current);
hash_node(rbt, new_current, name);
}
return (result);
}
......@@ -423,6 +402,10 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
current = NULL;
child = *root;
dns_name_init(&current_name, current_offsets);
dns_fixedname_init(&fnewname);
new_name = dns_fixedname_name(&fnewname);
nlabels = dns_name_countlabels(name);
hlabels = 0;
do {
current = child;
......@@ -462,6 +445,7 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
* the non-common parts of these two names should
* start a new tree.
*/
hlabels += common_labels;
if (compared == dns_namereln_subdomain) {
/*
* All of the existing labels are in common,
......@@ -588,7 +572,10 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;
rbt->nodecount++;
hash_node(rbt, new_current);
dns_name_getlabelsequence(name,
nlabels - hlabels,
hlabels, new_name);
hash_node(rbt, new_current, new_name);
if (common_labels ==
dns_name_countlabels(add_name)) {
......@@ -635,7 +622,7 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
dns_rbt_addonlevel(new_current, current, order, root);
rbt->nodecount++;
*nodep = new_current;
hash_node(rbt, new_current);
hash_node(rbt, new_current, name);
}
return (result);
......@@ -687,6 +674,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
dns_namereln_t compared;
isc_result_t result, saved_result;
unsigned int common_labels;
unsigned int hlabels = 0;
int order;
REQUIRE(VALID_RBT(rbt));
......@@ -782,11 +770,17 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
dns_name_init(&hash_name, NULL);
hashagain:
/*
* Hash includes tail.
*/
dns_name_getlabelsequence(name,
nlabels - tlabels,
hlabels + tlabels,
&hash_name);
hash = dns_name_fullhash(&hash_name, ISC_FALSE);
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;
......@@ -863,6 +857,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
*/
dns_name_split(search_name, common_labels,
search_name, NULL);
hlabels += common_labels;
/*
* This might be the closest enclosing name.
*/
......@@ -1475,10 +1470,10 @@ create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
#ifdef DNS_RBT_USEHASH
static inline void
hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
unsigned int hash;
compute_node_hash(node);
HASHVAL(node) = dns_name_fullhash(name, ISC_FALSE);
hash = HASHVAL(node) % rbt->hashsize;
HASHNEXT(node) = rbt->hashtable[hash];
......@@ -1539,14 +1534,14 @@ rehash(dns_rbt_t *rbt) {
}
static inline void
hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
REQUIRE(DNS_RBTNODE_VALID(node));