REQUIRE(dns_name_isabsolute(name));
REQUIRE(nodep != NULL && *nodep == NULL);
+ /*
+ * Dear future BIND developer,
+ *
+ * After you have tried attempting to optimize this routine by
+ * using the hashtable and have realized your folly, please
+ * append another cross ("X") below as a warning to the next
+ * future BIND developer:
+ *
+ * Number of victim developers: X
+ *
+ * I wish the past developer had included such a notice.
+ *
+ * Long form: Unlike dns_rbt_findnode(), this function does not
+ * lend itself to be optimized using the hashtable:
+ *
+ * 1. In the subtree where the insertion occurs, this function
+ * needs to have the insertion point and the order where the
+ * lookup terminated (i.e., at the insertion point where left or
+ * right child is NULL). This cannot be determined from the
+ * hashtable, so at least in that subtree, a BST O(log N) lookup
+ * is necessary.
+ *
+ * 2. Our RBT nodes contain not only single labels but label
+ * sequences to optimize space usage. So at every level, we have
+ * to look for a match in the hashtable for all superdomains in
+ * the rest of the name we're searching. This is an O(N)
+ * operation at least, here N being the label size of name, each
+ * of which is a hashtable lookup involving dns_name_equal()
+ * comparisons.
+ */
+
/*
* Create a copy of the name so the original name structure is
* not modified.
unsigned int options, dns_rbtfindcallback_t callback,
void *callback_arg)
{
- dns_rbtnode_t *current, *last_compared, *current_root;
+ dns_rbtnode_t *current, *last_compared;
dns_rbtnodechain_t localchain;
dns_name_t *search_name, current_name, *callback_name;
dns_fixedname_t fixedcallbackname, fixedsearchname;
saved_result = ISC_R_SUCCESS;
current = rbt->root;
- current_root = rbt->root;
while (ISC_LIKELY(current != NULL)) {
NODENAME(current, ¤t_name);
unsigned int hash;
/*
- * 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.
+ * The case of current not being a subtree 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);
+ INSIST(IS_ROOT(current));
nlabels = dns_name_countlabels(search_name);
/*
- * current_root is the root of the current level, so
+ * current is the root of the current level, so
* its parent is the same as its "up" pointer.
*/
- up_current = PARENT(current_root);
+ up_current = PARENT(current);
dns_name_init(&hash_name, NULL);
hashagain:
* Finally, head to the next tree level.
*/
current = DOWN(current);
- current_root = current;
-
} else {
/*
* Though there are labels in common, the
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id$ */
-
/* ! \file */
#include <config.h>
#include <stdio.h>
#include <string.h>
+#include <isc/hash.h>
+
#include <isc/crc64.h>
#include <isc/hmacmd5.h>
#include <isc/hmacsha.h>
}
}
+ATF_TC(isc_hash_function);
+ATF_TC_HEAD(isc_hash_function, tc) {
+ atf_tc_set_md_var(tc, "descr", "Hash function test");
+}
+ATF_TC_BODY(isc_hash_function, tc) {
+ unsigned int h1;
+ unsigned int h2;
+
+ UNUSED(tc);
+
+ /* Incremental hashing */
+
+ h1 = isc_hash_function(NULL, 0, ISC_TRUE, NULL);
+ h1 = isc_hash_function("This ", 5, ISC_TRUE, &h1);
+ h1 = isc_hash_function("is ", 3, ISC_TRUE, &h1);
+ h1 = isc_hash_function("a long test", 12, ISC_TRUE, &h1);
+
+ h2 = isc_hash_function("This is a long test", 20,
+ ISC_TRUE, NULL);
+
+ ATF_CHECK_EQ(h1, h2);
+
+ /* Immutability of hash function */
+ h1 = isc_hash_function(NULL, 0, ISC_TRUE, NULL);
+ h2 = isc_hash_function(NULL, 0, ISC_TRUE, NULL);
+
+ ATF_CHECK_EQ(h1, h2);
+
+ /* Hash function characteristics */
+ h1 = isc_hash_function("Hello world", 12, ISC_TRUE, NULL);
+ h2 = isc_hash_function("Hello world", 12, ISC_TRUE, NULL);
+
+ ATF_CHECK_EQ(h1, h2);
+
+ /* Case */
+ h1 = isc_hash_function("Hello world", 12, ISC_FALSE, NULL);
+ h2 = isc_hash_function("heLLo WorLd", 12, ISC_FALSE, NULL);
+
+ ATF_CHECK_EQ(h1, h2);
+
+ /* Unequal */
+ h1 = isc_hash_function("Hello world", 12, ISC_TRUE, NULL);
+ h2 = isc_hash_function("heLLo WorLd", 12, ISC_TRUE, NULL);
+
+ ATF_CHECK(h1 != h2);
+}
+
+
+ATF_TC(isc_hash_function_reverse);
+ATF_TC_HEAD(isc_hash_function_reverse, tc) {
+ atf_tc_set_md_var(tc, "descr", "Reverse hash function test");
+}
+ATF_TC_BODY(isc_hash_function_reverse, tc) {
+ unsigned int h1;
+ unsigned int h2;
+
+ UNUSED(tc);
+
+ /* Incremental hashing */
+
+ h1 = isc_hash_function_reverse(NULL, 0, ISC_TRUE, NULL);
+ h1 = isc_hash_function_reverse("\000", 1, ISC_TRUE, &h1);
+ h1 = isc_hash_function_reverse("\003org", 4, ISC_TRUE, &h1);
+ h1 = isc_hash_function_reverse("\007example", 8, ISC_TRUE, &h1);
+
+ h2 = isc_hash_function_reverse("\007example\003org\000", 13,
+ ISC_TRUE, NULL);
+
+ ATF_CHECK_EQ(h1, h2);
+
+ /* Immutability of hash function */
+ h1 = isc_hash_function_reverse(NULL, 0, ISC_TRUE, NULL);
+ h2 = isc_hash_function_reverse(NULL, 0, ISC_TRUE, NULL);
+
+ ATF_CHECK_EQ(h1, h2);
+
+ /* Hash function characteristics */
+ h1 = isc_hash_function_reverse("Hello world", 12, ISC_TRUE, NULL);
+ h2 = isc_hash_function_reverse("Hello world", 12, ISC_TRUE, NULL);
+
+ ATF_CHECK_EQ(h1, h2);
+
+ /* Case */
+ h1 = isc_hash_function_reverse("Hello world", 12, ISC_FALSE, NULL);
+ h2 = isc_hash_function_reverse("heLLo WorLd", 12, ISC_FALSE, NULL);
+
+ ATF_CHECK_EQ(h1, h2);
+
+ /* Unequal */
+ h1 = isc_hash_function_reverse("Hello world", 12, ISC_TRUE, NULL);
+ h2 = isc_hash_function_reverse("heLLo WorLd", 12, ISC_TRUE, NULL);
+
+ ATF_CHECK(h1 != h2);
+}
+
/*
* Main
*/
ATF_TP_ADD_TCS(tp) {
+ /*
+ * Tests of hash functions, including isc_hash and the
+ * various cryptographic hashes.
+ */
+ ATF_TP_ADD_TC(tp, isc_hash_function);
+ ATF_TP_ADD_TC(tp, isc_hash_function_reverse);
ATF_TP_ADD_TC(tp, isc_hmacmd5);
ATF_TP_ADD_TC(tp, isc_hmacsha1);
ATF_TP_ADD_TC(tp, isc_hmacsha224);
ATF_TP_ADD_TC(tp, isc_sha384);
ATF_TP_ADD_TC(tp, isc_sha512);
ATF_TP_ADD_TC(tp, isc_crc64);
+
return (atf_no_error());
}
-