]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
remove qp-zonedb.c and associated code
authorEvan Hunt <each@isc.org>
Wed, 6 Mar 2024 23:04:20 +0000 (15:04 -0800)
committerEvan Hunt <each@isc.org>
Fri, 8 Mar 2024 23:36:56 +0000 (15:36 -0800)
now that "qpzone" databases are available for use in zones, we no
longer need to retain the zone semantics in the "qp" database.

all zone-specific code has been removed from QPDB, and "configure
--with-zonedb" once again takes two values, rbt and qp.

some database API methods that are never used with a cache have
been removed from qpdb.c and qp-cachedb.c; these include newversion,
closeversion, subtractrdataset, and nodefullname.

bin/tests/system/dyndb/driver/db.c
configure.ac
lib/dns/Makefile.am
lib/dns/qp-cachedb.c
lib/dns/qp-zonedb.c [deleted file]
lib/dns/qpdb.c
lib/dns/qpdb_p.h
tests/dns/qpdb_test.c

index 9fa587d16d07f115e7052f161726c85afb66b340..90ddac13d130c6cc85d2bad07a272e1cdd129e76 100644 (file)
@@ -621,8 +621,8 @@ create_db(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
        /* Translate instance name to instance pointer. */
        sampledb->inst = driverarg;
 
-       /* Create internal instance of RBT DB implementation from BIND. */
-       CHECK(dns_db_create(mctx, "qp", origin, dns_dbtype_zone,
+       /* Create internal instance of DB implementation from BIND. */
+       CHECK(dns_db_create(mctx, ZONEDB_DEFAULT, origin, dns_dbtype_zone,
                            dns_rdataclass_in, 0, NULL, &sampledb->rbtdb));
 
        /* Create fake SOA, NS, and A records to make database loadable. */
index ec2f505122d48f7b8f6cfd05f17df2c54b05fbc2..070bccf102306e877680903f088961d1ec938715 100644 (file)
@@ -1570,9 +1570,8 @@ AS_IF([test -z "$DTRACE"],
 AC_SUBST([DTRACE])
 
 #
-# Which should be the default zone database, RBTDB, QPDB (based on dns_qp),
-# or QPZONE (based on dns_qpmulti)?
-# [pairwise: --with-zonedb=qp, --with-zonedb=qpzone, --with-zonedb=rbt]
+# Which should be the default zone database, RBTDB or QPZONE?
+# [pairwise: --with-zonedb=qp, --with-zonedb=rbt]
 #
 AC_ARG_WITH([zonedb],
            [AS_HELP_STRING([--with-zonedb=detect],[specify default zone database type (default is "qpzone")])],
@@ -1580,8 +1579,7 @@ AC_ARG_WITH([zonedb],
 zonedb="qpzone"
 AS_CASE([$with_zonedb],
        [RBT*|rbt*],[zonedb="rbt"],
-        [QP|qp],[zonedb="qp"],
-        [QPZ*|qpz*],[],
+        [QP|qp],[],
        [AC_MSG_ERROR([Unknown zone database type])]
        )
 AC_DEFINE_UNQUOTED([ZONEDB_DEFAULT], ["$zonedb"], [Default zone database type])
index 0cef1256cb34be90bef784b0a971768deeb020d8..ca4e06b3e179094babc0946fadd3675d09c5b0be 100644 (file)
@@ -224,7 +224,6 @@ libdns_la_SOURCES =                 \
        rbtdb.c                         \
        rbtdb_p.h                       \
        qp-cachedb.c                    \
-       qp-zonedb.c                     \
        qpdb_p.h                        \
        qpdb.c                          \
        rcode.c                         \
index cc0562bb7c06f5fda5beabfe57d658f37bb9e307..2c9b7bd1d5ea837dfcf515908bd9a163544bf01c 100644 (file)
@@ -1521,10 +1521,6 @@ expiredata(dns_db_t *db, dns_dbnode_t *node, void *data) {
 
 dns_dbmethods_t dns__qpdb_cachemethods = {
        .destroy = dns__qpdb_destroy,
-       .currentversion = dns__qpdb_currentversion,
-       .newversion = dns__qpdb_newversion,
-       .attachversion = dns__qpdb_attachversion,
-       .closeversion = dns__qpdb_closeversion,
        .findnode = dns__qpdb_findnode,
        .find = cache_find,
        .findzonecut = cache_findzonecut,
@@ -1534,7 +1530,6 @@ dns_dbmethods_t dns__qpdb_cachemethods = {
        .findrdataset = cache_findrdataset,
        .allrdatasets = dns__qpdb_allrdatasets,
        .addrdataset = dns__qpdb_addrdataset,
-       .subtractrdataset = dns__qpdb_subtractrdataset,
        .deleterdataset = dns__qpdb_deleterdataset,
        .nodecount = dns__qpdb_nodecount,
        .setloop = dns__qpdb_setloop,
@@ -1549,7 +1544,6 @@ dns_dbmethods_t dns__qpdb_cachemethods = {
        .unlocknode = dns__qpdb_unlocknode,
        .expiredata = expiredata,
        .deletedata = dns__qpdb_deletedata,
-       .nodefullname = dns__qpdb_nodefullname,
 };
 
 /*
diff --git a/lib/dns/qp-zonedb.c b/lib/dns/qp-zonedb.c
deleted file mode 100644 (file)
index 2c6b9ca..0000000
+++ /dev/null
@@ -1,2489 +0,0 @@
-/*
- * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
- *
- * SPDX-License-Identifier: MPL-2.0
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, you can obtain one at https://mozilla.org/MPL/2.0/.
- *
- * See the COPYRIGHT file distributed with this work for additional
- * information regarding copyright ownership.
- */
-
-/*! \file */
-
-#include <inttypes.h>
-#include <stdbool.h>
-#include <sys/mman.h>
-
-#include <isc/ascii.h>
-#include <isc/async.h>
-#include <isc/atomic.h>
-#include <isc/crc64.h>
-#include <isc/file.h>
-#include <isc/hash.h>
-#include <isc/hashmap.h>
-#include <isc/heap.h>
-#include <isc/hex.h>
-#include <isc/loop.h>
-#include <isc/mem.h>
-#include <isc/mutex.h>
-#include <isc/once.h>
-#include <isc/random.h>
-#include <isc/refcount.h>
-#include <isc/result.h>
-#include <isc/rwlock.h>
-#include <isc/serial.h>
-#include <isc/stdio.h>
-#include <isc/string.h>
-#include <isc/time.h>
-#include <isc/urcu.h>
-#include <isc/util.h>
-
-#include <dns/callbacks.h>
-#include <dns/db.h>
-#include <dns/dbiterator.h>
-#include <dns/fixedname.h>
-#include <dns/log.h>
-#include <dns/masterdump.h>
-#include <dns/nsec.h>
-#include <dns/nsec3.h>
-#include <dns/qp.h>
-#include <dns/rbt.h>
-#include <dns/rdata.h>
-#include <dns/rdataset.h>
-#include <dns/rdatasetiter.h>
-#include <dns/rdataslab.h>
-#include <dns/rdatastruct.h>
-#include <dns/stats.h>
-#include <dns/time.h>
-#include <dns/view.h>
-#include <dns/zone.h>
-#include <dns/zonekey.h>
-
-#include "db_p.h"
-#include "qpdb_p.h"
-
-#define CHECK(op)                            \
-       do {                                 \
-               result = (op);               \
-               if (result != ISC_R_SUCCESS) \
-                       goto failure;        \
-       } while (0)
-
-#define EXISTS(header)                                 \
-       ((atomic_load_acquire(&(header)->attributes) & \
-         DNS_SLABHEADERATTR_NONEXISTENT) == 0)
-#define NONEXISTENT(header)                            \
-       ((atomic_load_acquire(&(header)->attributes) & \
-         DNS_SLABHEADERATTR_NONEXISTENT) != 0)
-#define IGNORE(header)                                 \
-       ((atomic_load_acquire(&(header)->attributes) & \
-         DNS_SLABHEADERATTR_IGNORE) != 0)
-#define RESIGN(header)                                 \
-       ((atomic_load_acquire(&(header)->attributes) & \
-         DNS_SLABHEADERATTR_RESIGN) != 0)
-#define ANCIENT(header)                                \
-       ((atomic_load_acquire(&(header)->attributes) & \
-         DNS_SLABHEADERATTR_ANCIENT) != 0)
-
-#define QPDB_ATTR_LOADED  0x01
-#define QPDB_ATTR_LOADING 0x02
-
-static isc_result_t
-findnsec3node(dns_db_t *db, const dns_name_t *name, bool create,
-             dns_dbnode_t **nodep DNS__DB_FLARG) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-
-       REQUIRE(VALID_QPDB(qpdb));
-
-       return (dns__qpdb_findnodeintree(qpdb, qpdb->nsec3, name, create,
-                                        nodep DNS__DB_FLARG_PASS));
-}
-
-static isc_result_t
-check_zonecut(dns_qpdata_t *node, void *arg DNS__DB_FLARG) {
-       qpdb_search_t *search = arg;
-       dns_slabheader_t *header = NULL, *header_next = NULL;
-       dns_slabheader_t *dname_header = NULL, *sigdname_header = NULL;
-       dns_slabheader_t *ns_header = NULL;
-       dns_slabheader_t *found = NULL;
-       isc_result_t result = DNS_R_CONTINUE;
-       dns_qpdata_t *onode = NULL;
-       isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-       /*
-        * We only want to remember the topmost zone cut, since it's the one
-        * that counts, so we'll just continue if we've already found a
-        * zonecut.
-        */
-       if (search->zonecut != NULL) {
-               return (result);
-       }
-
-       onode = search->qpdb->origin_node;
-
-       NODE_RDLOCK(&(search->qpdb->node_locks[node->locknum].lock),
-                   &nlocktype);
-
-       /*
-        * Look for an NS or DNAME rdataset active in our version.
-        */
-       for (header = node->data; header != NULL; header = header_next) {
-               header_next = header->next;
-               if (header->type == dns_rdatatype_ns ||
-                   header->type == dns_rdatatype_dname ||
-                   header->type == DNS_SIGTYPE(dns_rdatatype_dname))
-               {
-                       do {
-                               if (header->serial <= search->serial &&
-                                   !IGNORE(header))
-                               {
-                                       /*
-                                        * Is this a "this rdataset doesn't
-                                        * exist" record?
-                                        */
-                                       if (NONEXISTENT(header)) {
-                                               header = NULL;
-                                       }
-                                       break;
-                               } else {
-                                       header = header->down;
-                               }
-                       } while (header != NULL);
-                       if (header != NULL) {
-                               if (header->type == dns_rdatatype_dname) {
-                                       dname_header = header;
-                               } else if (header->type ==
-                                          DNS_SIGTYPE(dns_rdatatype_dname))
-                               {
-                                       sigdname_header = header;
-                               } else if (node != onode ||
-                                          IS_STUB(search->qpdb))
-                               {
-                                       /*
-                                        * We've found an NS rdataset that
-                                        * isn't at the origin node.  We check
-                                        * that they're not at the origin node,
-                                        * because otherwise we'd erroneously
-                                        * treat the zone top as if it were
-                                        * a delegation.
-                                        */
-                                       ns_header = header;
-                               }
-                       }
-               }
-       }
-
-       /*
-        * Did we find anything?
-        */
-       if (!IS_STUB(search->qpdb) && ns_header != NULL) {
-               /*
-                * Note that NS has precedence over DNAME if both exist
-                * in a zone.  Otherwise DNAME take precedence over NS.
-                */
-               found = ns_header;
-               search->zonecut_sigheader = NULL;
-       } else if (dname_header != NULL) {
-               found = dname_header;
-               search->zonecut_sigheader = sigdname_header;
-       } else if (ns_header != NULL) {
-               found = ns_header;
-               search->zonecut_sigheader = NULL;
-       }
-
-       if (found != NULL) {
-               /*
-                * We increment the reference count on node to ensure that
-                * search->zonecut_header will still be valid later.
-                */
-               dns__qpdb_newref(search->qpdb, node,
-                                isc_rwlocktype_read DNS__DB_FLARG_PASS);
-               search->zonecut = node;
-               search->zonecut_header = found;
-               search->need_cleanup = true;
-               /*
-                * Since we've found a zonecut, anything beneath it is
-                * glue and is not subject to wildcard matching, so we
-                * may clear search->wild.
-                */
-               search->wild = false;
-               if ((search->options & DNS_DBFIND_GLUEOK) == 0) {
-                       /*
-                        * If the caller does not want to find glue, then
-                        * this is the best answer and the search should
-                        * stop now.
-                        */
-                       result = DNS_R_PARTIALMATCH;
-               } else {
-                       dns_name_t *zcname = NULL;
-
-                       /*
-                        * The search will continue beneath the zone cut.
-                        * This may or may not be the best match.  In case it
-                        * is, we need to remember the node name.
-                        */
-                       zcname = dns_fixedname_name(&search->zonecut_name);
-                       dns_name_copy(node->name, zcname);
-                       search->copy_name = true;
-               }
-       } else {
-               /*
-                * There is no zonecut at this node which is active in this
-                * version.
-                *
-                * If this is a "wild" node and the caller hasn't disabled
-                * wildcard matching, remember that we've seen a wild node
-                * in case we need to go searching for wildcard matches
-                * later on.
-                */
-               if (node->wild && (search->options & DNS_DBFIND_NOWILD) == 0) {
-                       search->wild = true;
-               }
-       }
-
-       NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock),
-                   &nlocktype);
-
-       return (result);
-}
-
-static isc_result_t
-setup_delegation(qpdb_search_t *search, dns_dbnode_t **nodep,
-                dns_name_t *foundname, dns_rdataset_t *rdataset,
-                dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
-       dns_name_t *zcname = NULL;
-       dns_typepair_t type;
-       dns_qpdata_t *node = NULL;
-
-       REQUIRE(search != NULL);
-       REQUIRE(search->zonecut != NULL);
-       REQUIRE(search->zonecut_header != NULL);
-
-       /*
-        * The caller MUST NOT be holding any node locks.
-        */
-
-       node = search->zonecut;
-       type = search->zonecut_header->type;
-
-       /*
-        * If we have to set foundname, we do it before anything else.
-        * If we were to set foundname after we had set nodep or bound the
-        * rdataset, then we'd have to undo that work if dns_name_copy()
-        * failed.  By setting foundname first, there's nothing to undo if
-        * we have trouble.
-        */
-       if (foundname != NULL && search->copy_name) {
-               zcname = dns_fixedname_name(&search->zonecut_name);
-               dns_name_copy(zcname, foundname);
-       }
-       if (nodep != NULL) {
-               /*
-                * Note that we don't have to increment the node's reference
-                * count here because we're going to use the reference we
-                * already have in the search block.
-                */
-               *nodep = node;
-               search->need_cleanup = false;
-       }
-       if (rdataset != NULL) {
-               isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-               NODE_RDLOCK(&(search->qpdb->node_locks[node->locknum].lock),
-                           &nlocktype);
-               dns__qpdb_bindrdataset(
-                       search->qpdb, node, search->zonecut_header, search->now,
-                       isc_rwlocktype_read, rdataset DNS__DB_FLARG_PASS);
-               if (sigrdataset != NULL && search->zonecut_sigheader != NULL) {
-                       dns__qpdb_bindrdataset(search->qpdb, node,
-                                              search->zonecut_sigheader,
-                                              search->now, isc_rwlocktype_read,
-                                              sigrdataset DNS__DB_FLARG_PASS);
-               }
-               NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock),
-                           &nlocktype);
-       }
-
-       if (type == dns_rdatatype_dname) {
-               return (DNS_R_DNAME);
-       }
-       return (DNS_R_DELEGATION);
-}
-
-typedef enum { FORWARD, BACK } direction_t;
-
-/*
- * Step backwards or forwards through the database until we find a
- * node with data in it for the desired version. If 'nextname' is not NULL,
- * and we found a predecessor or successor, save the name we found in it.
- * Return true if we found a predecessor or successor.
- */
-static bool
-step(qpdb_search_t *search, dns_qpiter_t *iter, direction_t direction,
-     dns_name_t *nextname) {
-       dns_fixedname_t fnodename;
-       dns_name_t *nodename = dns_fixedname_initname(&fnodename);
-       dns_qpdb_t *qpdb = NULL;
-       dns_qpdata_t *node = NULL;
-       isc_result_t result = ISC_R_SUCCESS;
-       dns_slabheader_t *header = NULL;
-
-       qpdb = search->qpdb;
-
-       result = dns_qpiter_current(iter, nodename, (void **)&node, NULL);
-
-       while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
-               isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-               NODE_RDLOCK(&(qpdb->node_locks[node->locknum].lock),
-                           &nlocktype);
-               for (header = node->data; header != NULL; header = header->next)
-               {
-                       if (header->serial <= search->serial &&
-                           !IGNORE(header) && EXISTS(header))
-                       {
-                               break;
-                       }
-               }
-               NODE_UNLOCK(&(qpdb->node_locks[node->locknum].lock),
-                           &nlocktype);
-               if (header != NULL) {
-                       break;
-               }
-
-               if (direction == FORWARD) {
-                       result = dns_qpiter_next(iter, nodename, (void **)&node,
-                                                NULL);
-               } else {
-                       result = dns_qpiter_prev(iter, nodename, (void **)&node,
-                                                NULL);
-               }
-       };
-       if (result == ISC_R_SUCCESS) {
-               if (nextname != NULL) {
-                       dns_name_copy(nodename, nextname);
-               }
-               return (true);
-       }
-       return (false);
-}
-
-/*
- * Use step() to find the successor to the current name, and then
- * check to see whether it's a subdomain of the current name. If so,
- * then this is an empty non-terminal in the currently active version
- * of the database.
- */
-static bool
-activeempty(qpdb_search_t *search, dns_qpiter_t *iter,
-           const dns_name_t *current) {
-       isc_result_t result;
-       dns_fixedname_t fnext;
-       dns_name_t *next = dns_fixedname_initname(&fnext);
-
-       result = dns_qpiter_next(iter, NULL, NULL, NULL);
-       if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
-               return (false);
-       }
-       return (step(search, iter, FORWARD, next) &&
-               dns_name_issubdomain(next, current));
-}
-
-static bool
-wildcard_blocked(qpdb_search_t *search, const dns_name_t *qname,
-                dns_name_t *wname) {
-       isc_result_t result;
-       dns_fixedname_t fnext;
-       dns_fixedname_t fprev;
-       dns_name_t *next = NULL, *prev = NULL;
-       dns_name_t name;
-       dns_name_t rname;
-       dns_name_t tname;
-       dns_qpiter_t iter;
-       bool check_next = false;
-       bool check_prev = false;
-       unsigned int n;
-
-       dns_name_init(&name, NULL);
-       dns_name_init(&tname, NULL);
-       dns_name_init(&rname, NULL);
-       next = dns_fixedname_initname(&fnext);
-       prev = dns_fixedname_initname(&fprev);
-
-       /*
-        * The qname seems to have matched a wildcard, but we
-        * need to find out if there's an empty nonterminal node
-        * between the wildcard level and the qname.
-        *
-        * search->iter should now be pointing at the predecessor
-        * of the searched-for name. We are using a local copy of the
-        * iterator so as not to change the state of search->iter.
-        * step() will walk backward until we find a predecessor with
-        * data.
-        */
-       iter = search->iter;
-       check_prev = step(search, &iter, BACK, prev);
-
-       /* Now reset the iterator and look for a successor with data. */
-       iter = search->iter;
-       result = dns_qpiter_next(&iter, NULL, NULL, NULL);
-       if (result == ISC_R_SUCCESS) {
-               check_next = step(search, &iter, FORWARD, next);
-       }
-
-       if (!check_prev && !check_next) {
-               /* No predecessor or successor was found at all? */
-               return (false);
-       }
-
-       dns_name_clone(qname, &rname);
-
-       /*
-        * Remove the wildcard label to find the terminal name.
-        */
-       n = dns_name_countlabels(wname);
-       dns_name_getlabelsequence(wname, 1, n - 1, &tname);
-
-       do {
-               if ((check_prev && dns_name_issubdomain(prev, &rname)) ||
-                   (check_next && dns_name_issubdomain(next, &rname)))
-               {
-                       return (true);
-               }
-
-               /*
-                * Remove the leftmost label from the qname and check again.
-                */
-               n = dns_name_countlabels(&rname);
-               dns_name_getlabelsequence(&rname, 1, n - 1, &rname);
-       } while (!dns_name_equal(&rname, &tname));
-
-       return (false);
-}
-
-static isc_result_t
-find_wildcard(qpdb_search_t *search, dns_qpdata_t **nodep,
-             const dns_name_t *qname) {
-       dns_slabheader_t *header = NULL;
-       isc_result_t result = ISC_R_NOTFOUND;
-       dns_qpdb_t *qpdb = NULL;
-       bool wild, active;
-
-       /*
-        * Caller must be holding the tree lock and MUST NOT be holding
-        * any node locks.
-        */
-
-       /*
-        * Examine each ancestor level.  If the level's wild bit
-        * is set, then construct the corresponding wildcard name and
-        * search for it.  If the wildcard node exists, and is active in
-        * this version, we're done.  If not, then we next check to see
-        * if the ancestor is active in this version.  If so, then there
-        * can be no possible wildcard match and again we're done.  If not,
-        * continue the search.
-        */
-
-       qpdb = search->qpdb;
-       for (int i = dns_qpchain_length(&search->chain) - 1; i >= 0; i--) {
-               dns_qpdata_t *node = NULL;
-               isc_rwlock_t *lock = NULL;
-               isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-               dns_qpchain_node(&search->chain, i, NULL, (void **)&node, NULL);
-               lock = &qpdb->node_locks[node->locknum].lock;
-
-               NODE_RDLOCK(lock, &nlocktype);
-               /*
-                * First we try to figure out if this node is active in
-                * the search's version.  We do this now, even though we
-                * may not need the information, because it simplifies the
-                * locking and code flow.
-                */
-               for (header = node->data; header != NULL; header = header->next)
-               {
-                       if (header->serial <= search->serial &&
-                           !IGNORE(header) && EXISTS(header) &&
-                           !ANCIENT(header))
-                       {
-                               break;
-                       }
-               }
-               active = (header != NULL);
-               wild = node->wild;
-               NODE_UNLOCK(lock, &nlocktype);
-
-               if (wild) {
-                       dns_qpdata_t *wnode = NULL;
-                       dns_fixedname_t fwname;
-                       dns_name_t *wname = NULL;
-                       dns_qpiter_t witer;
-
-                       /*
-                        * Construct the wildcard name for this level.
-                        */
-                       wname = dns_fixedname_initname(&fwname);
-                       result = dns_name_concatenate(dns_wildcardname,
-                                                     node->name, wname, NULL);
-                       if (result != ISC_R_SUCCESS) {
-                               break;
-                       }
-
-                       wnode = NULL;
-                       result = dns_qp_lookup(qpdb->tree, wname, NULL, &witer,
-                                              NULL, (void **)&wnode, NULL);
-                       if (result == ISC_R_SUCCESS) {
-                               /*
-                                * We have found the wildcard node.  If it
-                                * is active in the search's version, we're
-                                * done.
-                                */
-                               lock = &qpdb->node_locks[wnode->locknum].lock;
-                               NODE_RDLOCK(lock, &nlocktype);
-                               for (header = wnode->data; header != NULL;
-                                    header = header->next)
-                               {
-                                       if (header->serial <= search->serial &&
-                                           !IGNORE(header) && EXISTS(header) &&
-                                           !ANCIENT(header))
-                                       {
-                                               break;
-                                       }
-                               }
-                               NODE_UNLOCK(lock, &nlocktype);
-                               if (header != NULL ||
-                                   activeempty(search, &witer, wname))
-                               {
-                                       if (wildcard_blocked(search, qname,
-                                                            wname))
-                                       {
-                                               return (ISC_R_NOTFOUND);
-                                       }
-                                       /*
-                                        * The wildcard node is active!
-                                        *
-                                        * Note: result is still ISC_R_SUCCESS
-                                        * so we don't have to set it.
-                                        */
-                                       *nodep = wnode;
-                                       break;
-                               }
-                       } else if (result != ISC_R_NOTFOUND &&
-                                  result != DNS_R_PARTIALMATCH)
-                       {
-                               /*
-                                * An error has occurred.  Bail out.
-                                */
-                               break;
-                       }
-               }
-
-               if (active) {
-                       /*
-                        * The level node is active.  Any wildcarding
-                        * present at higher levels has no
-                        * effect and we're done.
-                        */
-                       result = ISC_R_NOTFOUND;
-                       break;
-               }
-       }
-
-       return (result);
-}
-
-static bool
-matchparams(dns_slabheader_t *header, qpdb_search_t *search) {
-       dns_rdata_t rdata = DNS_RDATA_INIT;
-       dns_rdata_nsec3_t nsec3;
-       unsigned char *raw = NULL;
-       unsigned int rdlen, count;
-       isc_region_t region;
-       isc_result_t result;
-
-       REQUIRE(header->type == dns_rdatatype_nsec3);
-
-       raw = (unsigned char *)header + sizeof(*header);
-       count = raw[0] * 256 + raw[1]; /* count */
-       raw += DNS_RDATASET_COUNT + DNS_RDATASET_LENGTH;
-
-       while (count-- > 0) {
-               rdlen = raw[0] * 256 + raw[1];
-               raw += DNS_RDATASET_ORDER + DNS_RDATASET_LENGTH;
-               region.base = raw;
-               region.length = rdlen;
-               dns_rdata_fromregion(&rdata, search->qpdb->common.rdclass,
-                                    dns_rdatatype_nsec3, &region);
-               raw += rdlen;
-               result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
-               INSIST(result == ISC_R_SUCCESS);
-               if (nsec3.hash == search->rbtversion->hash &&
-                   nsec3.iterations == search->rbtversion->iterations &&
-                   nsec3.salt_length == search->rbtversion->salt_length &&
-                   memcmp(nsec3.salt, search->rbtversion->salt,
-                          nsec3.salt_length) == 0)
-               {
-                       return (true);
-               }
-               dns_rdata_reset(&rdata);
-       }
-       return (false);
-}
-
-/*
- * Find node of the NSEC/NSEC3 record that is 'name'.
- */
-static isc_result_t
-previous_closest_nsec(dns_rdatatype_t type, qpdb_search_t *search,
-                     dns_name_t *name, dns_name_t *origin,
-                     dns_qpdata_t **nodep, dns_qpiter_t *nseciter,
-                     bool *firstp) {
-       dns_fixedname_t ftarget;
-       dns_name_t *target = NULL;
-       dns_qpdata_t *nsecnode = NULL;
-       isc_result_t result;
-
-       REQUIRE(nodep != NULL && *nodep == NULL);
-       REQUIRE(type == dns_rdatatype_nsec3 || firstp != NULL);
-
-       if (type == dns_rdatatype_nsec3) {
-               return (dns_qpiter_prev(&search->iter, name, (void **)nodep,
-                                       NULL));
-       }
-
-       target = dns_fixedname_initname(&ftarget);
-
-       for (;;) {
-               if (*firstp) {
-                       /*
-                        * Construct the name of the second node to check.
-                        * It is the first node sought in the NSEC tree.
-                        */
-                       *firstp = false;
-                       result = dns_name_concatenate(name, origin, target,
-                                                     NULL);
-                       if (result != ISC_R_SUCCESS) {
-                               return (result);
-                       }
-                       nsecnode = NULL;
-                       result = dns_qp_lookup(search->qpdb->nsec, name, NULL,
-                                              nseciter, NULL,
-                                              (void **)&nsecnode, NULL);
-                       if (result == ISC_R_SUCCESS) {
-                               /*
-                                * Since this was the first loop, finding the
-                                * name in the NSEC tree implies that the first
-                                * node checked in the main tree had an
-                                * unacceptable NSEC record.
-                                * Try the previous node in the NSEC tree.
-                                */
-                               result = dns_qpiter_prev(nseciter, name, NULL,
-                                                        NULL);
-                               if (result == DNS_R_NEWORIGIN) {
-                                       result = ISC_R_SUCCESS;
-                               }
-                       } else if (result == ISC_R_NOTFOUND ||
-                                  result == DNS_R_PARTIALMATCH)
-                       {
-                               /* The iterator is already where we want it */
-                               result = dns_qpiter_current(nseciter, name,
-                                                           NULL, NULL);
-                       }
-               } else {
-                       /*
-                        * This is a second or later trip through the auxiliary
-                        * tree for the name of a third or earlier NSEC node in
-                        * the main tree.  Previous trips through the NSEC tree
-                        * must have found nodes in the main tree with NSEC
-                        * records.  Perhaps they lacked signature records.
-                        */
-                       result = dns_qpiter_prev(nseciter, name, NULL, NULL);
-                       if (result == DNS_R_NEWORIGIN) {
-                               result = ISC_R_SUCCESS;
-                       }
-               }
-               if (result != ISC_R_SUCCESS) {
-                       return (result);
-               }
-
-               *nodep = NULL;
-               result = dns_qp_lookup(search->qpdb->tree, name, NULL,
-                                      &search->iter, &search->chain,
-                                      (void **)nodep, NULL);
-               if (result == ISC_R_SUCCESS) {
-                       return (result);
-               }
-
-               /*
-                * There should always be a node in the main tree with the
-                * same name as the node in the auxiliary NSEC tree, except for
-                * nodes in the auxiliary tree that are awaiting deletion.
-                */
-               if (result != DNS_R_PARTIALMATCH && result != ISC_R_NOTFOUND) {
-                       isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
-                                     DNS_LOGMODULE_CACHE, ISC_LOG_ERROR,
-                                     "previous_closest_nsec(): %s",
-                                     isc_result_totext(result));
-                       return (DNS_R_BADDB);
-               }
-       }
-}
-
-/*
- * Find the NSEC/NSEC3 which is or before the current point on the
- * search chain.  For NSEC3 records only NSEC3 records that match the
- * current NSEC3PARAM record are considered.
- */
-static isc_result_t
-find_closest_nsec(qpdb_search_t *search, dns_dbnode_t **nodep,
-                 dns_name_t *foundname, dns_rdataset_t *rdataset,
-                 dns_rdataset_t *sigrdataset, dns_qp_t *tree,
-                 bool secure DNS__DB_FLARG) {
-       dns_qpdata_t *node = NULL, *prevnode = NULL;
-       dns_slabheader_t *header = NULL, *header_next = NULL;
-       dns_qpiter_t nseciter;
-       bool empty_node;
-       isc_result_t result;
-       dns_fixedname_t fname, forigin;
-       dns_name_t *name = NULL, *origin = NULL;
-       dns_rdatatype_t type;
-       dns_typepair_t sigtype;
-       bool wraps;
-       bool first = true;
-       bool need_sig = secure;
-
-       if (tree == search->qpdb->nsec3) {
-               type = dns_rdatatype_nsec3;
-               sigtype = DNS_SIGTYPE(dns_rdatatype_nsec3);
-               wraps = true;
-       } else {
-               type = dns_rdatatype_nsec;
-               sigtype = DNS_SIGTYPE(dns_rdatatype_nsec);
-               wraps = false;
-       }
-
-       /*
-        * Use the auxiliary tree only starting with the second node in the
-        * hope that the original node will be right much of the time.
-        */
-       name = dns_fixedname_initname(&fname);
-       origin = dns_fixedname_initname(&forigin);
-
-       result = dns_qpiter_current(&search->iter, name, (void **)&node, NULL);
-       if (result != ISC_R_SUCCESS) {
-               return (result);
-       }
-
-again:
-       do {
-               dns_slabheader_t *found = NULL, *foundsig = NULL;
-               isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-               NODE_RDLOCK(&(search->qpdb->node_locks[node->locknum].lock),
-                           &nlocktype);
-               empty_node = true;
-               for (header = node->data; header != NULL; header = header_next)
-               {
-                       header_next = header->next;
-                       /*
-                        * Look for an active, extant NSEC or RRSIG NSEC.
-                        */
-                       do {
-                               if (header->serial <= search->serial &&
-                                   !IGNORE(header))
-                               {
-                                       /*
-                                        * Is this a "this rdataset doesn't
-                                        * exist" record?
-                                        */
-                                       if (NONEXISTENT(header)) {
-                                               header = NULL;
-                                       }
-                                       break;
-                               } else {
-                                       header = header->down;
-                               }
-                       } while (header != NULL);
-                       if (header != NULL) {
-                               /*
-                                * We now know that there is at least one
-                                * active rdataset at this node.
-                                */
-                               empty_node = false;
-                               if (header->type == type) {
-                                       found = header;
-                                       if (foundsig != NULL) {
-                                               break;
-                                       }
-                               } else if (header->type == sigtype) {
-                                       foundsig = header;
-                                       if (found != NULL) {
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               if (!empty_node) {
-                       if (found != NULL && search->rbtversion->havensec3 &&
-                           found->type == dns_rdatatype_nsec3 &&
-                           !matchparams(found, search))
-                       {
-                               empty_node = true;
-                               found = NULL;
-                               foundsig = NULL;
-                               result = previous_closest_nsec(
-                                       type, search, name, origin, &prevnode,
-                                       NULL, NULL);
-                       } else if (found != NULL &&
-                                  (foundsig != NULL || !need_sig))
-                       {
-                               /*
-                                * We've found the right NSEC/NSEC3 record.
-                                *
-                                * Note: for this to really be the right
-                                * NSEC record, it's essential that the NSEC
-                                * records of any nodes obscured by a zone
-                                * cut have been removed; we assume this is
-                                * the case.
-                                */
-                               result = dns_name_concatenate(name, origin,
-                                                             foundname, NULL);
-                               if (result == ISC_R_SUCCESS) {
-                                       if (nodep != NULL) {
-                                               dns__qpdb_newref(
-                                                       search->qpdb, node,
-                                                       isc_rwlocktype_read
-                                                               DNS__DB_FLARG_PASS);
-                                               *nodep = node;
-                                       }
-                                       dns__qpdb_bindrdataset(
-                                               search->qpdb, node, found,
-                                               search->now,
-                                               isc_rwlocktype_read,
-                                               rdataset DNS__DB_FLARG_PASS);
-                                       if (foundsig != NULL) {
-                                               dns__qpdb_bindrdataset(
-                                                       search->qpdb, node,
-                                                       foundsig, search->now,
-                                                       isc_rwlocktype_read,
-                                                       sigrdataset
-                                                               DNS__DB_FLARG_PASS);
-                                       }
-                               }
-                       } else if (found == NULL && foundsig == NULL) {
-                               /*
-                                * This node is active, but has no NSEC or
-                                * RRSIG NSEC.  That means it's glue or
-                                * other obscured zone data that isn't
-                                * relevant for our search.  Treat the
-                                * node as if it were empty and keep looking.
-                                */
-                               empty_node = true;
-                               result = previous_closest_nsec(
-                                       type, search, name, origin, &prevnode,
-                                       &nseciter, &first);
-                       } else {
-                               /*
-                                * We found an active node, but either the
-                                * NSEC or the RRSIG NSEC is missing.  This
-                                * shouldn't happen.
-                                */
-                               result = DNS_R_BADDB;
-                       }
-               } else {
-                       /*
-                        * This node isn't active.  We've got to keep
-                        * looking.
-                        */
-                       result = previous_closest_nsec(type, search, name,
-                                                      origin, &prevnode,
-                                                      &nseciter, &first);
-               }
-               NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock),
-                           &nlocktype);
-               node = prevnode;
-               prevnode = NULL;
-       } while (empty_node && result == ISC_R_SUCCESS);
-
-       if (result == ISC_R_NOMORE && wraps) {
-               result = dns_qpiter_prev(&search->iter, name, (void **)&node,
-                                        NULL);
-               if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
-                       wraps = false;
-                       goto again;
-               }
-       }
-
-       /*
-        * If the result is ISC_R_NOMORE, then we got to the beginning of
-        * the database and didn't find a NSEC record.  This shouldn't
-        * happen.
-        */
-       if (result == ISC_R_NOMORE) {
-               result = DNS_R_BADDB;
-       }
-
-       return (result);
-}
-
-static isc_result_t
-zone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
-         dns_rdatatype_t type, unsigned int options,
-         isc_stdtime_t now ISC_ATTR_UNUSED, dns_dbnode_t **nodep,
-         dns_name_t *foundname, dns_rdataset_t *rdataset,
-         dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
-       dns_qpdata_t *node = NULL;
-       isc_result_t result;
-       qpdb_search_t search;
-       bool cname_ok = true;
-       bool close_version = false;
-       bool maybe_zonecut = false;
-       bool at_zonecut = false;
-       bool wild = false;
-       bool empty_node;
-       dns_slabheader_t *header = NULL, *header_next = NULL;
-       dns_slabheader_t *found = NULL, *nsecheader = NULL;
-       dns_slabheader_t *foundsig = NULL, *cnamesig = NULL, *nsecsig = NULL;
-       dns_typepair_t sigtype;
-       bool active;
-       isc_rwlock_t *lock = NULL;
-       dns_qp_t *tree = NULL;
-       isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-       isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
-
-       REQUIRE(VALID_QPDB((dns_qpdb_t *)db));
-       INSIST(version == NULL ||
-              ((dns_qpdb_version_t *)version)->qpdb == (dns_qpdb_t *)db);
-
-       /*
-        * If the caller didn't supply a version, attach to the current
-        * version.
-        */
-       if (version == NULL) {
-               dns__qpdb_currentversion(db, &version);
-               close_version = true;
-       }
-
-       search = (qpdb_search_t){
-               .qpdb = (dns_qpdb_t *)db,
-               .rbtversion = version,
-               .serial = ((dns_qpdb_version_t *)version)->serial,
-               .options = options,
-       };
-       dns_fixedname_init(&search.zonecut_name);
-
-       TREE_RDLOCK(&search.qpdb->tree_lock, &tlocktype);
-
-       /*
-        * Search down from the root of the tree.
-        */
-       tree = (options & DNS_DBFIND_FORCENSEC3) != 0 ? search.qpdb->nsec3
-                                                     : search.qpdb->tree;
-       result = dns_qp_lookup(tree, name, foundname, &search.iter,
-                              &search.chain, (void **)&node, NULL);
-
-       /*
-        * Check the QP chain to see if there's a node above us with a
-        * active DNAME or NS rdatasets.
-        *
-        * We're only interested in nodes above QNAME, so if the result
-        * was success, then we skip the last item in the chain.
-        */
-       unsigned int len = dns_qpchain_length(&search.chain);
-       if (result == ISC_R_SUCCESS) {
-               len--;
-       }
-
-       for (unsigned int i = 0; i < len; i++) {
-               isc_result_t zcresult;
-               dns_qpdata_t *encloser = NULL;
-
-               dns_qpchain_node(&search.chain, i, NULL, (void **)&encloser,
-                                NULL);
-
-               if (encloser->find_callback) {
-                       zcresult = check_zonecut(
-                               encloser, (void *)&search DNS__DB_FLARG_PASS);
-                       if (zcresult != DNS_R_CONTINUE) {
-                               result = DNS_R_PARTIALMATCH;
-                               search.chain.len = i - 1;
-                               node = encloser;
-                               break;
-                       }
-               }
-       }
-
-       if (result == DNS_R_PARTIALMATCH) {
-       partial_match:
-               if (search.zonecut != NULL) {
-                       result = setup_delegation(
-                               &search, nodep, foundname, rdataset,
-                               sigrdataset DNS__DB_FLARG_PASS);
-                       goto tree_exit;
-               }
-
-               if (search.wild) {
-                       /*
-                        * At least one of the levels in the search chain
-                        * potentially has a wildcard.  For each such level,
-                        * we must see if there's a matching wildcard active
-                        * in the current version.
-                        */
-                       result = find_wildcard(&search, &node, name);
-                       if (result == ISC_R_SUCCESS) {
-                               dns_name_copy(name, foundname);
-                               wild = true;
-                               goto found;
-                       } else if (result != ISC_R_NOTFOUND) {
-                               goto tree_exit;
-                       }
-               }
-
-               active = false;
-               if ((options & DNS_DBFIND_FORCENSEC3) == 0) {
-                       /*
-                        * The NSEC3 tree won't have empty nodes,
-                        * so it isn't necessary to check for them.
-                        */
-                       dns_qpiter_t iter = search.iter;
-                       active = activeempty(&search, &iter, name);
-               }
-
-               /*
-                * If we're here, then the name does not exist, is not
-                * beneath a zonecut, and there's no matching wildcard.
-                */
-               if ((search.rbtversion->secure &&
-                    !search.rbtversion->havensec3) ||
-                   (search.options & DNS_DBFIND_FORCENSEC3) != 0)
-               {
-                       result = find_closest_nsec(
-                               &search, nodep, foundname, rdataset,
-                               sigrdataset, tree,
-                               search.rbtversion->secure DNS__DB_FLARG_PASS);
-                       if (result == ISC_R_SUCCESS) {
-                               result = active ? DNS_R_EMPTYNAME
-                                               : DNS_R_NXDOMAIN;
-                       }
-               } else {
-                       result = active ? DNS_R_EMPTYNAME : DNS_R_NXDOMAIN;
-               }
-               goto tree_exit;
-       } else if (result != ISC_R_SUCCESS) {
-               goto tree_exit;
-       }
-
-found:
-       /*
-        * We have found a node whose name is the desired name, or we
-        * have matched a wildcard.
-        */
-
-       lock = &search.qpdb->node_locks[node->locknum].lock;
-       NODE_RDLOCK(lock, &nlocktype);
-
-       if (search.zonecut != NULL) {
-               /*
-                * If we're beneath a zone cut, we don't want to look for
-                * CNAMEs because they're not legitimate zone glue.
-                */
-               cname_ok = false;
-       } else {
-               /*
-                * The node may be a zone cut itself.  If it might be one,
-                * make sure we check for it later.
-                *
-                * DS records live above the zone cut in ordinary zone so
-                * we want to ignore any referral.
-                *
-                * Stub zones don't have anything "above" the delegation so
-                * we always return a referral.
-                */
-               if (node->find_callback && ((node != search.qpdb->origin_node &&
-                                            !dns_rdatatype_atparent(type)) ||
-                                           IS_STUB(search.qpdb)))
-               {
-                       maybe_zonecut = true;
-               }
-       }
-
-       /*
-        * Certain DNSSEC types are not subject to CNAME matching
-        * (RFC4035, section 2.5 and RFC3007).
-        *
-        * We don't check for RRSIG, because we don't store RRSIG records
-        * directly.
-        */
-       if (type == dns_rdatatype_key || type == dns_rdatatype_nsec) {
-               cname_ok = false;
-       }
-
-       /*
-        * We now go looking for rdata...
-        */
-
-       found = NULL;
-       foundsig = NULL;
-       sigtype = DNS_SIGTYPE(type);
-       nsecheader = NULL;
-       nsecsig = NULL;
-       cnamesig = NULL;
-       empty_node = true;
-       for (header = node->data; header != NULL; header = header_next) {
-               header_next = header->next;
-               /*
-                * Look for an active, extant rdataset.
-                */
-               do {
-                       if (header->serial <= search.serial && !IGNORE(header))
-                       {
-                               /*
-                                * Is this a "this rdataset doesn't
-                                * exist" record?
-                                */
-                               if (NONEXISTENT(header)) {
-                                       header = NULL;
-                               }
-                               break;
-                       } else {
-                               header = header->down;
-                       }
-               } while (header != NULL);
-               if (header != NULL) {
-                       /*
-                        * We now know that there is at least one active
-                        * rdataset at this node.
-                        */
-                       empty_node = false;
-
-                       /*
-                        * Do special zone cut handling, if requested.
-                        */
-                       if (maybe_zonecut && header->type == dns_rdatatype_ns) {
-                               /*
-                                * We increment the reference count on node to
-                                * ensure that search->zonecut_header will
-                                * still be valid later.
-                                */
-                               dns__qpdb_newref(search.qpdb, node,
-                                                nlocktype DNS__DB_FLARG_PASS);
-                               search.zonecut = node;
-                               search.zonecut_header = header;
-                               search.zonecut_sigheader = NULL;
-                               search.need_cleanup = true;
-                               maybe_zonecut = false;
-                               at_zonecut = true;
-                               /*
-                                * It is not clear if KEY should still be
-                                * allowed at the parent side of the zone
-                                * cut or not.  It is needed for RFC3007
-                                * validated updates.
-                                */
-                               if ((search.options & DNS_DBFIND_GLUEOK) == 0 &&
-                                   type != dns_rdatatype_nsec &&
-                                   type != dns_rdatatype_key)
-                               {
-                                       /*
-                                        * Glue is not OK, but any answer we
-                                        * could return would be glue.  Return
-                                        * the delegation.
-                                        */
-                                       found = NULL;
-                                       break;
-                               }
-                               if (found != NULL && foundsig != NULL) {
-                                       break;
-                               }
-                       }
-
-                       /*
-                        * If the NSEC3 record doesn't match the chain
-                        * we are using behave as if it isn't here.
-                        */
-                       if (header->type == dns_rdatatype_nsec3 &&
-                           !matchparams(header, &search))
-                       {
-                               NODE_UNLOCK(lock, &nlocktype);
-                               goto partial_match;
-                       }
-                       /*
-                        * If we found a type we were looking for,
-                        * remember it.
-                        */
-                       if (header->type == type || type == dns_rdatatype_any ||
-                           (header->type == dns_rdatatype_cname && cname_ok))
-                       {
-                               /*
-                                * We've found the answer!
-                                */
-                               found = header;
-                               if (header->type == dns_rdatatype_cname &&
-                                   cname_ok)
-                               {
-                                       /*
-                                        * We may be finding a CNAME instead
-                                        * of the desired type.
-                                        *
-                                        * If we've already got the CNAME RRSIG,
-                                        * use it, otherwise change sigtype
-                                        * so that we find it.
-                                        */
-                                       if (cnamesig != NULL) {
-                                               foundsig = cnamesig;
-                                       } else {
-                                               sigtype = DNS_SIGTYPE(
-                                                       dns_rdatatype_cname);
-                                       }
-                               }
-                               /*
-                                * If we've got all we need, end the search.
-                                */
-                               if (!maybe_zonecut && foundsig != NULL) {
-                                       break;
-                               }
-                       } else if (header->type == sigtype) {
-                               /*
-                                * We've found the RRSIG rdataset for our
-                                * target type.  Remember it.
-                                */
-                               foundsig = header;
-                               /*
-                                * If we've got all we need, end the search.
-                                */
-                               if (!maybe_zonecut && found != NULL) {
-                                       break;
-                               }
-                       } else if (header->type == dns_rdatatype_nsec &&
-                                  !search.rbtversion->havensec3)
-                       {
-                               /*
-                                * Remember a NSEC rdataset even if we're
-                                * not specifically looking for it, because
-                                * we might need it later.
-                                */
-                               nsecheader = header;
-                       } else if (header->type ==
-                                          DNS_SIGTYPE(dns_rdatatype_nsec) &&
-                                  !search.rbtversion->havensec3)
-                       {
-                               /*
-                                * If we need the NSEC rdataset, we'll also
-                                * need its signature.
-                                */
-                               nsecsig = header;
-                       } else if (cname_ok &&
-                                  header->type ==
-                                          DNS_SIGTYPE(dns_rdatatype_cname))
-                       {
-                               /*
-                                * If we get a CNAME match, we'll also need
-                                * its signature.
-                                */
-                               cnamesig = header;
-                       }
-               }
-       }
-
-       if (empty_node) {
-               /*
-                * We have an exact match for the name, but there are no
-                * active rdatasets in the desired version.  That means that
-                * this node doesn't exist in the desired version, and that
-                * we really have a partial match.
-                */
-               if (!wild) {
-                       NODE_UNLOCK(lock, &nlocktype);
-                       goto partial_match;
-               }
-       }
-
-       /*
-        * If we didn't find what we were looking for...
-        */
-       if (found == NULL) {
-               if (search.zonecut != NULL) {
-                       /*
-                        * We were trying to find glue at a node beneath a
-                        * zone cut, but didn't.
-                        *
-                        * Return the delegation.
-                        */
-                       NODE_UNLOCK(lock, &nlocktype);
-                       result = setup_delegation(
-                               &search, nodep, foundname, rdataset,
-                               sigrdataset DNS__DB_FLARG_PASS);
-                       goto tree_exit;
-               }
-               /*
-                * The desired type doesn't exist.
-                */
-               result = DNS_R_NXRRSET;
-               if (search.rbtversion->secure &&
-                   !search.rbtversion->havensec3 &&
-                   (nsecheader == NULL || nsecsig == NULL))
-               {
-                       /*
-                        * The zone is secure but there's no NSEC,
-                        * or the NSEC has no signature!
-                        */
-                       if (!wild) {
-                               result = DNS_R_BADDB;
-                               goto node_exit;
-                       }
-
-                       NODE_UNLOCK(lock, &nlocktype);
-                       result = find_closest_nsec(
-                               &search, nodep, foundname, rdataset,
-                               sigrdataset, search.qpdb->tree,
-                               search.rbtversion->secure DNS__DB_FLARG_PASS);
-                       if (result == ISC_R_SUCCESS) {
-                               result = DNS_R_EMPTYWILD;
-                       }
-                       goto tree_exit;
-               }
-               if (nodep != NULL) {
-                       dns__qpdb_newref(search.qpdb, node,
-                                        nlocktype DNS__DB_FLARG_PASS);
-                       *nodep = node;
-               }
-               if ((search.rbtversion->secure &&
-                    !search.rbtversion->havensec3))
-               {
-                       dns__qpdb_bindrdataset(search.qpdb, node, nsecheader, 0,
-                                              nlocktype,
-                                              rdataset DNS__DB_FLARG_PASS);
-                       if (nsecsig != NULL) {
-                               dns__qpdb_bindrdataset(
-                                       search.qpdb, node, nsecsig, 0,
-                                       nlocktype,
-                                       sigrdataset DNS__DB_FLARG_PASS);
-                       }
-               }
-               if (wild) {
-                       foundname->attributes.wildcard = true;
-               }
-               goto node_exit;
-       }
-
-       /*
-        * We found what we were looking for, or we found a CNAME.
-        */
-
-       if (type != found->type && type != dns_rdatatype_any &&
-           found->type == dns_rdatatype_cname)
-       {
-               /*
-                * We weren't doing an ANY query and we found a CNAME instead
-                * of the type we were looking for, so we need to indicate
-                * that result to the caller.
-                */
-               result = DNS_R_CNAME;
-       } else if (search.zonecut != NULL) {
-               /*
-                * If we're beneath a zone cut, we must indicate that the
-                * result is glue, unless we're actually at the zone cut
-                * and the type is NSEC or KEY.
-                */
-               if (search.zonecut == node) {
-                       /*
-                        * It is not clear if KEY should still be
-                        * allowed at the parent side of the zone
-                        * cut or not.  It is needed for RFC3007
-                        * validated updates.
-                        */
-                       if (type == dns_rdatatype_nsec ||
-                           type == dns_rdatatype_nsec3 ||
-                           type == dns_rdatatype_key)
-                       {
-                               result = ISC_R_SUCCESS;
-                       } else if (type == dns_rdatatype_any) {
-                               result = DNS_R_ZONECUT;
-                       } else {
-                               result = DNS_R_GLUE;
-                       }
-               } else {
-                       result = DNS_R_GLUE;
-               }
-       } else {
-               /*
-                * An ordinary successful query!
-                */
-               result = ISC_R_SUCCESS;
-       }
-
-       if (nodep != NULL) {
-               if (!at_zonecut) {
-                       dns__qpdb_newref(search.qpdb, node,
-                                        nlocktype DNS__DB_FLARG_PASS);
-               } else {
-                       search.need_cleanup = false;
-               }
-               *nodep = node;
-       }
-
-       if (type != dns_rdatatype_any) {
-               dns__qpdb_bindrdataset(search.qpdb, node, found, 0, nlocktype,
-                                      rdataset DNS__DB_FLARG_PASS);
-               if (foundsig != NULL) {
-                       dns__qpdb_bindrdataset(search.qpdb, node, foundsig, 0,
-                                              nlocktype,
-                                              sigrdataset DNS__DB_FLARG_PASS);
-               }
-       }
-
-       if (wild) {
-               foundname->attributes.wildcard = true;
-       }
-
-node_exit:
-       NODE_UNLOCK(lock, &nlocktype);
-
-tree_exit:
-       TREE_UNLOCK(&search.qpdb->tree_lock, &tlocktype);
-
-       /*
-        * If we found a zonecut but aren't going to use it, we have to
-        * let go of it.
-        */
-       if (search.need_cleanup) {
-               node = search.zonecut;
-               INSIST(node != NULL);
-               lock = &(search.qpdb->node_locks[node->locknum].lock);
-
-               NODE_RDLOCK(lock, &nlocktype);
-               dns__qpdb_decref(search.qpdb, node, 0, &nlocktype, &tlocktype,
-                                true, false DNS__DB_FLARG_PASS);
-               NODE_UNLOCK(lock, &nlocktype);
-               INSIST(tlocktype == isc_rwlocktype_none);
-       }
-
-       if (close_version) {
-               dns__qpdb_closeversion(db, &version, false DNS__DB_FLARG_PASS);
-       }
-
-       return (result);
-}
-
-static isc_result_t
-zone_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
-                 dns_rdatatype_t type, dns_rdatatype_t covers,
-                 isc_stdtime_t now, dns_rdataset_t *rdataset,
-                 dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       dns_qpdata_t *qpnode = (dns_qpdata_t *)node;
-       dns_slabheader_t *header = NULL, *header_next = NULL;
-       dns_slabheader_t *found = NULL, *foundsig = NULL;
-       uint32_t serial;
-       dns_qpdb_version_t *rbtversion = version;
-       bool close_version = false;
-       dns_typepair_t matchtype, sigmatchtype;
-       isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-       REQUIRE(VALID_QPDB(qpdb));
-       REQUIRE(type != dns_rdatatype_any);
-       INSIST(rbtversion == NULL || rbtversion->qpdb == qpdb);
-
-       if (rbtversion == NULL) {
-               dns__qpdb_currentversion(
-                       db, (dns_dbversion_t **)(void *)(&rbtversion));
-               close_version = true;
-       }
-       serial = rbtversion->serial;
-       now = 0;
-
-       NODE_RDLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
-
-       matchtype = DNS_TYPEPAIR_VALUE(type, covers);
-       if (covers == 0) {
-               sigmatchtype = DNS_SIGTYPE(type);
-       } else {
-               sigmatchtype = 0;
-       }
-
-       for (header = qpnode->data; header != NULL; header = header_next) {
-               header_next = header->next;
-               do {
-                       if (header->serial <= serial && !IGNORE(header)) {
-                               /*
-                                * Is this a "this rdataset doesn't
-                                * exist" record?
-                                */
-                               if (NONEXISTENT(header)) {
-                                       header = NULL;
-                               }
-                               break;
-                       } else {
-                               header = header->down;
-                       }
-               } while (header != NULL);
-               if (header != NULL) {
-                       /*
-                        * We have an active, extant rdataset.  If it's a
-                        * type we're looking for, remember it.
-                        */
-                       if (header->type == matchtype) {
-                               found = header;
-                               if (foundsig != NULL) {
-                                       break;
-                               }
-                       } else if (header->type == sigmatchtype) {
-                               foundsig = header;
-                               if (found != NULL) {
-                                       break;
-                               }
-                       }
-               }
-       }
-       if (found != NULL) {
-               dns__qpdb_bindrdataset(qpdb, qpnode, found, now,
-                                      isc_rwlocktype_read,
-                                      rdataset DNS__DB_FLARG_PASS);
-               if (foundsig != NULL) {
-                       dns__qpdb_bindrdataset(qpdb, qpnode, foundsig, now,
-                                              isc_rwlocktype_read,
-                                              sigrdataset DNS__DB_FLARG_PASS);
-               }
-       }
-
-       NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
-
-       if (close_version) {
-               dns__qpdb_closeversion(
-                       db, (dns_dbversion_t **)(void *)(&rbtversion),
-                       false DNS__DB_FLARG_PASS);
-       }
-
-       if (found == NULL) {
-               return (ISC_R_NOTFOUND);
-       }
-
-       return (ISC_R_SUCCESS);
-}
-
-static bool
-delegating_type(dns_qpdb_t *qpdb, dns_qpdata_t *node, dns_typepair_t type) {
-       if (type == dns_rdatatype_dname ||
-           (type == dns_rdatatype_ns &&
-            (node != qpdb->origin_node || IS_STUB(qpdb))))
-       {
-               return (true);
-       }
-       return (false);
-}
-
-/*
- * load a non-NSEC3 node in the main tree and optionally to the auxiliary NSEC
- */
-static isc_result_t
-loadnode(dns_qpdb_t *qpdb, const dns_name_t *name, dns_qpdata_t **nodep,
-        bool hasnsec) {
-       isc_result_t noderesult, nsecresult;
-       dns_qpdata_t *nsecnode = NULL, *node = NULL;
-
-       noderesult = dns_qp_getname(qpdb->tree, name, (void **)&node, NULL);
-       if (noderesult != ISC_R_SUCCESS) {
-               INSIST(node == NULL);
-               node = dns_qpdata_create(qpdb, name);
-               noderesult = dns_qp_insert(qpdb->tree, node, 0);
-               INSIST(noderesult == ISC_R_SUCCESS);
-               dns_qpdata_unref(node);
-       } else if (noderesult == ISC_R_SUCCESS) {
-               /*
-                * Add a node to the auxiliary NSEC tree for an old node
-                * just now getting an NSEC record.
-                */
-               if (node->nsec == DNS_DB_NSEC_HAS_NSEC) {
-                       goto done;
-               }
-       } else {
-               goto done;
-       }
-
-       if (!hasnsec) {
-               goto done;
-       }
-
-       /*
-        * Build the auxiliary tree for NSECs as we go.
-        * This tree speeds searches for closest NSECs that would otherwise
-        * need to examine many irrelevant nodes in large TLDs.
-        *
-        * Add nodes to the auxiliary tree after corresponding nodes have
-        * been added to the main tree.
-        */
-       nsecresult = dns_qp_getname(qpdb->nsec, name, (void **)&nsecnode, NULL);
-       if (nsecresult == ISC_R_SUCCESS) {
-#if 1 /* 0 */
-               isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
-                             DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,
-                             "addnode: NSEC node already exists");
-#endif /* if 1 */
-               node->nsec = DNS_DB_NSEC_HAS_NSEC;
-               goto done;
-       } else {
-               INSIST(nsecnode == NULL);
-               nsecnode = dns_qpdata_create(qpdb, name);
-               nsecnode->nsec = DNS_DB_NSEC_NSEC;
-               nsecresult = dns_qp_insert(qpdb->nsec, nsecnode, 0);
-               INSIST(nsecresult == ISC_R_SUCCESS);
-               dns_qpdata_detach(&nsecnode);
-       }
-       node->nsec = DNS_DB_NSEC_HAS_NSEC;
-
-done:
-       if (noderesult == ISC_R_SUCCESS || noderesult == ISC_R_EXISTS) {
-               *nodep = node;
-       }
-
-       return (noderesult);
-}
-
-static isc_result_t
-loading_addrdataset(void *arg, const dns_name_t *name,
-                   dns_rdataset_t *rdataset DNS__DB_FLARG) {
-       qpdb_load_t *loadctx = arg;
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)loadctx->db;
-       dns_qpdata_t *node = NULL;
-       isc_result_t result;
-       isc_region_t region;
-       dns_slabheader_t *newheader = NULL;
-       isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-       REQUIRE(rdataset->rdclass == qpdb->common.rdclass);
-
-       /*
-        * SOA records are only allowed at top of zone.
-        */
-       if (rdataset->type == dns_rdatatype_soa &&
-           !dns_name_equal(name, &qpdb->common.origin))
-       {
-               return (DNS_R_NOTZONETOP);
-       }
-
-       if (rdataset->type != dns_rdatatype_nsec3 &&
-           rdataset->covers != dns_rdatatype_nsec3)
-       {
-               dns__qpzone_addwildcards(qpdb, name, false);
-       }
-
-       if (dns_name_iswildcard(name)) {
-               /*
-                * NS record owners cannot legally be wild cards.
-                */
-               if (rdataset->type == dns_rdatatype_ns) {
-                       return (DNS_R_INVALIDNS);
-               }
-               /*
-                * NSEC3 record owners cannot legally be wild cards.
-                */
-               if (rdataset->type == dns_rdatatype_nsec3) {
-                       return (DNS_R_INVALIDNSEC3);
-               }
-               result = dns__qpzone_wildcardmagic(qpdb, name, false);
-               if (result != ISC_R_SUCCESS) {
-                       return (result);
-               }
-       }
-
-       if (rdataset->type == dns_rdatatype_nsec3 ||
-           rdataset->covers == dns_rdatatype_nsec3)
-       {
-               result = dns_qp_getname(qpdb->nsec3, name, (void **)&node,
-                                       NULL);
-               if (result != ISC_R_SUCCESS) {
-                       INSIST(node == NULL);
-                       node = dns_qpdata_create(qpdb, name);
-                       result = dns_qp_insert(qpdb->nsec3, node, 0);
-                       INSIST(result == ISC_R_SUCCESS);
-                       dns_qpdata_unref(node);
-               }
-               node->nsec = DNS_DB_NSEC_NSEC3;
-       } else if (rdataset->type == dns_rdatatype_nsec) {
-               result = loadnode(qpdb, name, &node, true);
-       } else {
-               result = loadnode(qpdb, name, &node, false);
-       }
-       if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
-               return (result);
-       }
-       if (result == ISC_R_SUCCESS) {
-               node->locknum = node->hashval % qpdb->node_lock_count;
-       }
-
-       result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
-                                           &region, sizeof(dns_slabheader_t));
-       if (result != ISC_R_SUCCESS) {
-               return (result);
-       }
-       newheader = (dns_slabheader_t *)region.base;
-       *newheader = (dns_slabheader_t){
-               .type = DNS_TYPEPAIR_VALUE(rdataset->type, rdataset->covers),
-               .ttl = rdataset->ttl + loadctx->now,
-               .trust = rdataset->trust,
-               .node = node,
-               .serial = 1,
-               .count = 1,
-       };
-
-       dns_slabheader_reset(newheader, (dns_db_t *)qpdb, node);
-       dns_slabheader_setownercase(newheader, name);
-
-       if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
-               DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_RESIGN);
-               newheader->resign =
-                       (isc_stdtime_t)(dns_time64_from32(rdataset->resign) >>
-                                       1);
-               newheader->resign_lsb = rdataset->resign & 0x1;
-       }
-
-       NODE_WRLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
-       result = dns__qpdb_add(qpdb, node, name, qpdb->current_version,
-                              newheader, DNS_DBADD_MERGE, true, NULL,
-                              0 DNS__DB_FLARG_PASS);
-       NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
-
-       if (result == ISC_R_SUCCESS &&
-           delegating_type(qpdb, node, rdataset->type))
-       {
-               node->find_callback = 1;
-       } else if (result == DNS_R_UNCHANGED) {
-               result = ISC_R_SUCCESS;
-       }
-
-       return (result);
-}
-
-static isc_result_t
-beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
-       qpdb_load_t *loadctx = NULL;
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-
-       REQUIRE(DNS_CALLBACK_VALID(callbacks));
-       REQUIRE(VALID_QPDB(qpdb));
-
-       loadctx = isc_mem_get(qpdb->common.mctx, sizeof(*loadctx));
-
-       loadctx->db = db;
-       loadctx->now = 0;
-
-       RWLOCK(&qpdb->lock, isc_rwlocktype_write);
-
-       REQUIRE((qpdb->attributes & (QPDB_ATTR_LOADED | QPDB_ATTR_LOADING)) ==
-               0);
-       qpdb->attributes |= QPDB_ATTR_LOADING;
-
-       RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
-
-       callbacks->add = loading_addrdataset;
-       callbacks->add_private = loadctx;
-
-       return (ISC_R_SUCCESS);
-}
-
-static isc_result_t
-endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
-       qpdb_load_t *loadctx = NULL;
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-
-       REQUIRE(VALID_QPDB(qpdb));
-       REQUIRE(DNS_CALLBACK_VALID(callbacks));
-       loadctx = callbacks->add_private;
-       REQUIRE(loadctx != NULL);
-       REQUIRE(loadctx->db == db);
-
-       RWLOCK(&qpdb->lock, isc_rwlocktype_write);
-
-       REQUIRE((qpdb->attributes & QPDB_ATTR_LOADING) != 0);
-       REQUIRE((qpdb->attributes & QPDB_ATTR_LOADED) == 0);
-
-       qpdb->attributes &= ~QPDB_ATTR_LOADING;
-       qpdb->attributes |= QPDB_ATTR_LOADED;
-
-       /*
-        * If there's a KEY rdataset at the zone origin containing a
-        * zone key, we consider the zone secure.
-        */
-       if (qpdb->origin_node != NULL) {
-               dns_dbversion_t *version = qpdb->current_version;
-               RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
-               dns__qpdb_setsecure(db, version, qpdb->origin_node);
-       } else {
-               RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
-       }
-
-       callbacks->add = NULL;
-       callbacks->add_private = NULL;
-
-       isc_mem_put(qpdb->common.mctx, loadctx, sizeof(*loadctx));
-
-       return (ISC_R_SUCCESS);
-}
-
-static bool
-issecure(dns_db_t *db) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       bool secure;
-
-       REQUIRE(VALID_QPDB(qpdb));
-
-       RWLOCK(&qpdb->lock, isc_rwlocktype_read);
-       secure = qpdb->current_version->secure;
-       RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
-
-       return (secure);
-}
-
-static isc_result_t
-getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash,
-                  uint8_t *flags, uint16_t *iterations, unsigned char *salt,
-                  size_t *salt_length) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       isc_result_t result = ISC_R_NOTFOUND;
-       dns_qpdb_version_t *rbtversion = version;
-
-       REQUIRE(VALID_QPDB(qpdb));
-       INSIST(rbtversion == NULL || rbtversion->qpdb == qpdb);
-
-       RWLOCK(&qpdb->lock, isc_rwlocktype_read);
-       if (rbtversion == NULL) {
-               rbtversion = qpdb->current_version;
-       }
-
-       if (rbtversion->havensec3) {
-               if (hash != NULL) {
-                       *hash = rbtversion->hash;
-               }
-               if (salt != NULL && salt_length != NULL) {
-                       REQUIRE(*salt_length >= rbtversion->salt_length);
-                       memmove(salt, rbtversion->salt,
-                               rbtversion->salt_length);
-               }
-               if (salt_length != NULL) {
-                       *salt_length = rbtversion->salt_length;
-               }
-               if (iterations != NULL) {
-                       *iterations = rbtversion->iterations;
-               }
-               if (flags != NULL) {
-                       *flags = rbtversion->flags;
-               }
-               result = ISC_R_SUCCESS;
-       }
-       RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
-
-       return (result);
-}
-
-static isc_result_t
-getsize(dns_db_t *db, dns_dbversion_t *version, uint64_t *records,
-       uint64_t *xfrsize) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       isc_result_t result = ISC_R_SUCCESS;
-       dns_qpdb_version_t *rbtversion = version;
-
-       REQUIRE(VALID_QPDB(qpdb));
-       INSIST(rbtversion == NULL || rbtversion->qpdb == qpdb);
-
-       RWLOCK(&qpdb->lock, isc_rwlocktype_read);
-       if (rbtversion == NULL) {
-               rbtversion = qpdb->current_version;
-       }
-
-       RWLOCK(&rbtversion->rwlock, isc_rwlocktype_read);
-       SET_IF_NOT_NULL(records, rbtversion->records);
-
-       SET_IF_NOT_NULL(xfrsize, rbtversion->xfrsize);
-       RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_read);
-       RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
-
-       return (result);
-}
-
-static isc_result_t
-setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       dns_slabheader_t *header, oldheader;
-       isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-       REQUIRE(VALID_QPDB(qpdb));
-       REQUIRE(!IS_CACHE(qpdb));
-       REQUIRE(rdataset != NULL);
-       REQUIRE(rdataset->methods == &dns_rdataslab_rdatasetmethods);
-
-       header = dns_slabheader_fromrdataset(rdataset);
-
-       NODE_WRLOCK(&qpdb->node_locks[QPDB_HEADERNODE(header)->locknum].lock,
-                   &nlocktype);
-
-       oldheader = *header;
-
-       /*
-        * Only break the heap invariant (by adjusting resign and resign_lsb)
-        * if we are going to be restoring it by calling isc_heap_increased
-        * or isc_heap_decreased.
-        */
-       if (resign != 0) {
-               header->resign = (isc_stdtime_t)(dns_time64_from32(resign) >>
-                                                1);
-               header->resign_lsb = resign & 0x1;
-       }
-       if (header->heap_index != 0) {
-               INSIST(RESIGN(header));
-               if (resign == 0) {
-                       isc_heap_delete(
-                               qpdb->heaps[QPDB_HEADERNODE(header)->locknum],
-                               header->heap_index);
-                       header->heap_index = 0;
-                       header->heap = NULL;
-               } else if (qpdb->sooner(header, &oldheader)) {
-                       isc_heap_increased(
-                               qpdb->heaps[QPDB_HEADERNODE(header)->locknum],
-                               header->heap_index);
-               } else if (qpdb->sooner(&oldheader, header)) {
-                       isc_heap_decreased(
-                               qpdb->heaps[QPDB_HEADERNODE(header)->locknum],
-                               header->heap_index);
-               }
-       } else if (resign != 0) {
-               DNS_SLABHEADER_SETATTR(header, DNS_SLABHEADERATTR_RESIGN);
-               dns__qpzone_resigninsert(qpdb, QPDB_HEADERNODE(header)->locknum,
-                                        header);
-       }
-       NODE_UNLOCK(&qpdb->node_locks[QPDB_HEADERNODE(header)->locknum].lock,
-                   &nlocktype);
-       return (ISC_R_SUCCESS);
-}
-
-static isc_result_t
-getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
-              dns_name_t *foundname DNS__DB_FLARG) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       dns_slabheader_t *header = NULL, *this = NULL;
-       unsigned int i;
-       isc_result_t result = ISC_R_NOTFOUND;
-       unsigned int locknum = 0;
-       isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
-       isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-       REQUIRE(VALID_QPDB(qpdb));
-
-       TREE_RDLOCK(&qpdb->tree_lock, &tlocktype);
-
-       for (i = 0; i < qpdb->node_lock_count; i++) {
-               NODE_RDLOCK(&qpdb->node_locks[i].lock, &nlocktype);
-
-               /*
-                * Find for the earliest signing time among all of the
-                * heaps, each of which is covered by a different bucket
-                * lock.
-                */
-               this = isc_heap_element(qpdb->heaps[i], 1);
-               if (this == NULL) {
-                       /* Nothing found; unlock and try the next heap. */
-                       NODE_UNLOCK(&qpdb->node_locks[i].lock, &nlocktype);
-                       continue;
-               }
-
-               if (header == NULL) {
-                       /*
-                        * Found a signing time: retain the bucket lock and
-                        * preserve the lock number so we can unlock it
-                        * later.
-                        */
-                       header = this;
-                       locknum = i;
-                       nlocktype = isc_rwlocktype_none;
-               } else if (qpdb->sooner(this, header)) {
-                       /*
-                        * Found an earlier signing time; release the
-                        * previous bucket lock and retain this one instead.
-                        */
-                       NODE_UNLOCK(&qpdb->node_locks[locknum].lock,
-                                   &nlocktype);
-                       header = this;
-                       locknum = i;
-               } else {
-                       /*
-                        * Earliest signing time in this heap isn't
-                        * an improvement; unlock and try the next heap.
-                        */
-                       NODE_UNLOCK(&qpdb->node_locks[i].lock, &nlocktype);
-               }
-       }
-
-       if (header != NULL) {
-               nlocktype = isc_rwlocktype_read;
-               /*
-                * Found something; pass back the answer and unlock
-                * the bucket.
-                */
-               dns__qpdb_bindrdataset(qpdb, QPDB_HEADERNODE(header), header, 0,
-                                      isc_rwlocktype_read,
-                                      rdataset DNS__DB_FLARG_PASS);
-
-               if (foundname != NULL) {
-                       dns_name_copy(QPDB_HEADERNODE(header)->name, foundname);
-               }
-
-               NODE_UNLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
-
-               result = ISC_R_SUCCESS;
-       }
-
-       TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
-
-       return (result);
-}
-
-static isc_result_t
-setgluecachestats(dns_db_t *db, isc_stats_t *stats) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-
-       REQUIRE(VALID_QPDB(qpdb));
-       REQUIRE(!IS_CACHE(qpdb) && !IS_STUB(qpdb));
-       REQUIRE(stats != NULL);
-
-       isc_stats_attach(stats, &qpdb->gluecachestats);
-       return (ISC_R_SUCCESS);
-}
-
-static dns_glue_t *
-new_gluelist(isc_mem_t *mctx, dns_name_t *name) {
-       dns_glue_t *glue = isc_mem_get(mctx, sizeof(*glue));
-       *glue = (dns_glue_t){ 0 };
-       dns_name_t *gluename = dns_fixedname_initname(&glue->fixedname);
-
-       isc_mem_attach(mctx, &glue->mctx);
-       dns_name_copy(name, gluename);
-
-       return (glue);
-}
-
-static isc_result_t
-glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
-               dns_rdataset_t *unused DNS__DB_FLARG) {
-       dns_glue_additionaldata_ctx_t *ctx = NULL;
-       isc_result_t result;
-       dns_fixedname_t fixedname_a;
-       dns_name_t *name_a = NULL;
-       dns_rdataset_t rdataset_a, sigrdataset_a;
-       dns_qpdata_t *node_a = NULL;
-       dns_fixedname_t fixedname_aaaa;
-       dns_name_t *name_aaaa = NULL;
-       dns_rdataset_t rdataset_aaaa, sigrdataset_aaaa;
-       dns_qpdata_t *node_aaaa = NULL;
-       dns_glue_t *glue = NULL;
-
-       UNUSED(unused);
-
-       /*
-        * NS records want addresses in additional records.
-        */
-       INSIST(qtype == dns_rdatatype_a);
-
-       ctx = (dns_glue_additionaldata_ctx_t *)arg;
-
-       name_a = dns_fixedname_initname(&fixedname_a);
-       dns_rdataset_init(&rdataset_a);
-       dns_rdataset_init(&sigrdataset_a);
-
-       name_aaaa = dns_fixedname_initname(&fixedname_aaaa);
-       dns_rdataset_init(&rdataset_aaaa);
-       dns_rdataset_init(&sigrdataset_aaaa);
-
-       result = zone_find(ctx->db, name, ctx->version, dns_rdatatype_a,
-                          DNS_DBFIND_GLUEOK, 0, (dns_dbnode_t **)&node_a,
-                          name_a, &rdataset_a,
-                          &sigrdataset_a DNS__DB_FLARG_PASS);
-       if (result == DNS_R_GLUE) {
-               glue = new_gluelist(ctx->db->mctx, name_a);
-
-               dns_rdataset_init(&glue->rdataset_a);
-               dns_rdataset_init(&glue->sigrdataset_a);
-               dns_rdataset_init(&glue->rdataset_aaaa);
-               dns_rdataset_init(&glue->sigrdataset_aaaa);
-
-               dns_rdataset_clone(&rdataset_a, &glue->rdataset_a);
-               if (dns_rdataset_isassociated(&sigrdataset_a)) {
-                       dns_rdataset_clone(&sigrdataset_a,
-                                          &glue->sigrdataset_a);
-               }
-       }
-
-       result = zone_find(ctx->db, name, ctx->version, dns_rdatatype_aaaa,
-                          DNS_DBFIND_GLUEOK, 0, (dns_dbnode_t **)&node_aaaa,
-                          name_aaaa, &rdataset_aaaa,
-                          &sigrdataset_aaaa DNS__DB_FLARG_PASS);
-       if (result == DNS_R_GLUE) {
-               if (glue == NULL) {
-                       glue = new_gluelist(ctx->db->mctx, name_aaaa);
-
-                       dns_rdataset_init(&glue->rdataset_a);
-                       dns_rdataset_init(&glue->sigrdataset_a);
-                       dns_rdataset_init(&glue->rdataset_aaaa);
-                       dns_rdataset_init(&glue->sigrdataset_aaaa);
-               } else {
-                       INSIST(node_a == node_aaaa);
-                       INSIST(dns_name_equal(name_a, name_aaaa));
-               }
-
-               dns_rdataset_clone(&rdataset_aaaa, &glue->rdataset_aaaa);
-               if (dns_rdataset_isassociated(&sigrdataset_aaaa)) {
-                       dns_rdataset_clone(&sigrdataset_aaaa,
-                                          &glue->sigrdataset_aaaa);
-               }
-       }
-
-       /*
-        * If the currently processed NS record is in-bailiwick, mark any glue
-        * RRsets found for it with DNS_RDATASETATTR_REQUIRED.  Note that for
-        * simplicity, glue RRsets for all in-bailiwick NS records are marked
-        * this way, even though dns_message_rendersection() only checks the
-        * attributes for the first rdataset associated with the first name
-        * added to the ADDITIONAL section.
-        */
-       if (glue != NULL && dns_name_issubdomain(name, ctx->nodename)) {
-               if (dns_rdataset_isassociated(&glue->rdataset_a)) {
-                       glue->rdataset_a.attributes |=
-                               DNS_RDATASETATTR_REQUIRED;
-               }
-               if (dns_rdataset_isassociated(&glue->rdataset_aaaa)) {
-                       glue->rdataset_aaaa.attributes |=
-                               DNS_RDATASETATTR_REQUIRED;
-               }
-       }
-
-       if (glue != NULL) {
-               glue->next = ctx->glue_list;
-               ctx->glue_list = glue;
-       }
-
-       result = ISC_R_SUCCESS;
-
-       if (dns_rdataset_isassociated(&rdataset_a)) {
-               dns_rdataset_disassociate(&rdataset_a);
-       }
-       if (dns_rdataset_isassociated(&sigrdataset_a)) {
-               dns_rdataset_disassociate(&sigrdataset_a);
-       }
-
-       if (dns_rdataset_isassociated(&rdataset_aaaa)) {
-               dns_rdataset_disassociate(&rdataset_aaaa);
-       }
-       if (dns_rdataset_isassociated(&sigrdataset_aaaa)) {
-               dns_rdataset_disassociate(&sigrdataset_aaaa);
-       }
-
-       if (node_a != NULL) {
-               dns__db_detachnode(ctx->db,
-                                  (dns_dbnode_t *)&node_a DNS__DB_FLARG_PASS);
-       }
-       if (node_aaaa != NULL) {
-               dns__db_detachnode(
-                       ctx->db, (dns_dbnode_t *)&node_aaaa DNS__DB_FLARG_PASS);
-       }
-
-       return (result);
-}
-
-#define IS_REQUIRED_GLUE(r) (((r)->attributes & DNS_RDATASETATTR_REQUIRED) != 0)
-
-static void
-addglue_to_message(dns_glue_t *ge, dns_message_t *msg) {
-       for (; ge != NULL; ge = ge->next) {
-               dns_name_t *name = NULL;
-               dns_rdataset_t *rdataset_a = NULL;
-               dns_rdataset_t *sigrdataset_a = NULL;
-               dns_rdataset_t *rdataset_aaaa = NULL;
-               dns_rdataset_t *sigrdataset_aaaa = NULL;
-               dns_name_t *gluename = dns_fixedname_name(&ge->fixedname);
-               bool prepend_name = false;
-
-               dns_message_gettempname(msg, &name);
-
-               dns_name_copy(gluename, name);
-
-               if (dns_rdataset_isassociated(&ge->rdataset_a)) {
-                       dns_message_gettemprdataset(msg, &rdataset_a);
-               }
-
-               if (dns_rdataset_isassociated(&ge->sigrdataset_a)) {
-                       dns_message_gettemprdataset(msg, &sigrdataset_a);
-               }
-
-               if (dns_rdataset_isassociated(&ge->rdataset_aaaa)) {
-                       dns_message_gettemprdataset(msg, &rdataset_aaaa);
-               }
-
-               if (dns_rdataset_isassociated(&ge->sigrdataset_aaaa)) {
-                       dns_message_gettemprdataset(msg, &sigrdataset_aaaa);
-               }
-
-               if (rdataset_a != NULL) {
-                       dns_rdataset_clone(&ge->rdataset_a, rdataset_a);
-                       ISC_LIST_APPEND(name->list, rdataset_a, link);
-                       if (IS_REQUIRED_GLUE(rdataset_a)) {
-                               prepend_name = true;
-                       }
-               }
-
-               if (sigrdataset_a != NULL) {
-                       dns_rdataset_clone(&ge->sigrdataset_a, sigrdataset_a);
-                       ISC_LIST_APPEND(name->list, sigrdataset_a, link);
-               }
-
-               if (rdataset_aaaa != NULL) {
-                       dns_rdataset_clone(&ge->rdataset_aaaa, rdataset_aaaa);
-                       ISC_LIST_APPEND(name->list, rdataset_aaaa, link);
-                       if (IS_REQUIRED_GLUE(rdataset_aaaa)) {
-                               prepend_name = true;
-                       }
-               }
-               if (sigrdataset_aaaa != NULL) {
-                       dns_rdataset_clone(&ge->sigrdataset_aaaa,
-                                          sigrdataset_aaaa);
-                       ISC_LIST_APPEND(name->list, sigrdataset_aaaa, link);
-               }
-
-               dns_message_addname(msg, name, DNS_SECTION_ADDITIONAL);
-
-               /*
-                * When looking for required glue, dns_message_rendersection()
-                * only processes the first rdataset associated with the first
-                * name added to the ADDITIONAL section.  dns_message_addname()
-                * performs an append on the list of names in a given section,
-                * so if any glue record was marked as required, we need to
-                * move the name it is associated with to the beginning of the
-                * list for the ADDITIONAL section or else required glue might
-                * not be rendered.
-                */
-               if (prepend_name) {
-                       ISC_LIST_UNLINK(msg->sections[DNS_SECTION_ADDITIONAL],
-                                       name, link);
-                       ISC_LIST_PREPEND(msg->sections[DNS_SECTION_ADDITIONAL],
-                                        name, link);
-               }
-       }
-}
-
-static dns_glue_t *
-newglue(dns_qpdb_t *qpdb, dns_qpdb_version_t *rbtversion, dns_qpdata_t *node,
-       dns_rdataset_t *rdataset) {
-       dns_fixedname_t nodename;
-       dns_glue_additionaldata_ctx_t ctx = {
-               .db = (dns_db_t *)qpdb,
-               .version = (dns_dbversion_t *)rbtversion,
-               .nodename = dns_fixedname_initname(&nodename),
-       };
-
-       /*
-        * Get the owner name of the NS RRset - it will be necessary for
-        * identifying required glue in glue_nsdname_cb() (by
-        * determining which NS records in the delegation are
-        * in-bailiwick).
-        */
-       dns__qpdb_nodefullname((dns_db_t *)qpdb, node, ctx.nodename);
-
-       (void)dns_rdataset_additionaldata(rdataset, dns_rootname,
-                                         glue_nsdname_cb, &ctx);
-
-       return (ctx.glue_list);
-}
-
-static isc_result_t
-addglue(dns_db_t *db, dns_dbversion_t *version, dns_rdataset_t *rdataset,
-       dns_message_t *msg) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       dns_qpdb_version_t *rbtversion = version;
-       dns_qpdata_t *node = (dns_qpdata_t *)rdataset->slab.node;
-       dns_slabheader_t *header = dns_slabheader_fromrdataset(rdataset);
-
-       REQUIRE(rdataset->type == dns_rdatatype_ns);
-       REQUIRE(qpdb == (dns_qpdb_t *)rdataset->slab.db);
-       REQUIRE(qpdb == rbtversion->qpdb);
-       REQUIRE(!IS_CACHE(qpdb) && !IS_STUB(qpdb));
-
-       rcu_read_lock();
-
-       dns_glue_t *glue = rcu_dereference(header->glue_list);
-       if (glue == NULL) {
-               /* No cached glue was found in the table. Get new glue. */
-               glue = newglue(qpdb, rbtversion, node, rdataset);
-
-               /* Cache the glue or (void *)-1 if no glue was found. */
-               dns_glue_t *old_glue = rcu_cmpxchg_pointer(
-                       &header->glue_list, NULL, (glue) ? glue : (void *)-1);
-               if (old_glue != NULL) {
-                       /* Somebody else was faster */
-                       dns__qpdb_freeglue(glue);
-                       glue = old_glue;
-               } else if (glue != NULL) {
-                       cds_wfs_push(&rbtversion->glue_stack,
-                                    &header->wfs_node);
-               }
-       }
-
-       /* We have a cached result. Add it to the message and return. */
-
-       if (qpdb->gluecachestats != NULL) {
-               isc_stats_increment(
-                       qpdb->gluecachestats,
-                       (glue == (void *)-1)
-                               ? dns_gluecachestatscounter_hits_absent
-                               : dns_gluecachestatscounter_hits_present);
-       }
-
-       /*
-        * (void *)-1 is a special value that means no glue is present in the
-        * zone.
-        */
-       if (glue != (void *)-1) {
-               addglue_to_message(glue, msg);
-       }
-
-       rcu_read_unlock();
-
-       return (ISC_R_SUCCESS);
-}
-
-dns_dbmethods_t dns__qpdb_zonemethods = {
-       .destroy = dns__qpdb_destroy,
-       .beginload = beginload,
-       .endload = endload,
-       .currentversion = dns__qpdb_currentversion,
-       .newversion = dns__qpdb_newversion,
-       .attachversion = dns__qpdb_attachversion,
-       .closeversion = dns__qpdb_closeversion,
-       .findnode = dns__qpdb_findnode,
-       .find = zone_find,
-       .attachnode = dns__qpdb_attachnode,
-       .detachnode = dns__qpdb_detachnode,
-       .createiterator = dns__qpdb_createiterator,
-       .findrdataset = zone_findrdataset,
-       .allrdatasets = dns__qpdb_allrdatasets,
-       .addrdataset = dns__qpdb_addrdataset,
-       .subtractrdataset = dns__qpdb_subtractrdataset,
-       .deleterdataset = dns__qpdb_deleterdataset,
-       .issecure = issecure,
-       .nodecount = dns__qpdb_nodecount,
-       .setloop = dns__qpdb_setloop,
-       .getoriginnode = dns__qpdb_getoriginnode,
-       .getnsec3parameters = getnsec3parameters,
-       .findnsec3node = findnsec3node,
-       .setsigningtime = setsigningtime,
-       .getsigningtime = getsigningtime,
-       .getsize = getsize,
-       .setgluecachestats = setgluecachestats,
-       .locknode = dns__qpdb_locknode,
-       .unlocknode = dns__qpdb_unlocknode,
-       .addglue = addglue,
-       .deletedata = dns__qpdb_deletedata,
-       .nodefullname = dns__qpdb_nodefullname,
-};
-
-void
-dns__qpzone_resigninsert(dns_qpdb_t *qpdb, int idx,
-                        dns_slabheader_t *newheader) {
-       INSIST(!IS_CACHE(qpdb));
-       INSIST(newheader->heap_index == 0);
-       INSIST(!ISC_LINK_LINKED(newheader, link));
-
-       isc_heap_insert(qpdb->heaps[idx], newheader);
-       newheader->heap = qpdb->heaps[idx];
-}
-
-void
-dns__qpzone_resigndelete(dns_qpdb_t *qpdb, dns_qpdb_version_t *version,
-                        dns_slabheader_t *header DNS__DB_FLARG) {
-       /*
-        * Remove the old header from the heap
-        */
-       if (header != NULL && header->heap_index != 0) {
-               isc_heap_delete(qpdb->heaps[QPDB_HEADERNODE(header)->locknum],
-                               header->heap_index);
-               header->heap_index = 0;
-               if (version != NULL) {
-                       dns__qpdb_newref(
-                               qpdb, QPDB_HEADERNODE(header),
-                               isc_rwlocktype_write DNS__DB_FLARG_PASS);
-                       ISC_LIST_APPEND(version->resigned_list, header, link);
-               }
-       }
-}
-
-isc_result_t
-dns__qpzone_wildcardmagic(dns_qpdb_t *qpdb, const dns_name_t *name, bool lock) {
-       isc_result_t result;
-       dns_name_t foundname;
-       dns_offsets_t offsets;
-       unsigned int n;
-       dns_qpdata_t *node = NULL;
-       isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-       dns_name_init(&foundname, offsets);
-       n = dns_name_countlabels(name);
-       INSIST(n >= 2);
-       n--;
-       dns_name_getlabelsequence(name, 1, n, &foundname);
-
-       result = dns_qp_getname(qpdb->tree, &foundname, (void **)&node, NULL);
-       if (result != ISC_R_SUCCESS) {
-               INSIST(node == NULL);
-               node = dns_qpdata_create(qpdb, &foundname);
-               result = dns_qp_insert(qpdb->tree, node, 0);
-               INSIST(result == ISC_R_SUCCESS);
-               dns_qpdata_unref(node);
-       }
-
-       INSIST(result == ISC_R_SUCCESS);
-       node->nsec = DNS_DB_NSEC_NORMAL;
-       node->find_callback = 1;
-       if (lock) {
-               NODE_WRLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
-       }
-       node->wild = 1;
-       if (lock) {
-               NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
-       }
-       return (ISC_R_SUCCESS);
-}
-
-isc_result_t
-dns__qpzone_addwildcards(dns_qpdb_t *qpdb, const dns_name_t *name, bool lock) {
-       isc_result_t result;
-       dns_name_t foundname;
-       dns_offsets_t offsets;
-       unsigned int n, l, i;
-
-       dns_name_init(&foundname, offsets);
-       n = dns_name_countlabels(name);
-       l = dns_name_countlabels(&qpdb->common.origin);
-       i = l + 1;
-       while (i < n) {
-               dns_qpdata_t *node = NULL;
-               dns_name_getlabelsequence(name, n - i, i, &foundname);
-               if (dns_name_iswildcard(&foundname)) {
-                       result = dns__qpzone_wildcardmagic(qpdb, &foundname,
-                                                          lock);
-                       if (result != ISC_R_SUCCESS) {
-                               return (result);
-                       }
-
-                       result = dns_qp_getname(qpdb->tree, name,
-                                               (void **)&node, NULL);
-                       if (result != ISC_R_SUCCESS) {
-                               INSIST(node == NULL);
-                               node = dns_qpdata_create(qpdb, name);
-                               node->nsec = DNS_DB_NSEC_NORMAL;
-                               result = dns_qp_insert(qpdb->tree, node, 0);
-                               INSIST(result == ISC_R_SUCCESS);
-                               dns_qpdata_detach(&node);
-                       } else if (result == ISC_R_SUCCESS) {
-                               node->nsec = DNS_DB_NSEC_NORMAL;
-                       }
-               }
-               i++;
-       }
-       return (ISC_R_SUCCESS);
-}
index 8ed465b1821130cea74923ef86035f248b33ed3a..38e479588b06ce161ac8030d4be14d3346500f46 100644 (file)
@@ -59,7 +59,6 @@
 #include <dns/stats.h>
 #include <dns/time.h>
 #include <dns/view.h>
-#include <dns/zone.h>
 #include <dns/zonekey.h>
 
 #include "db_p.h"
@@ -90,9 +89,6 @@
 #define STALE_WINDOW(header)                           \
        ((atomic_load_acquire(&(header)->attributes) & \
          DNS_SLABHEADERATTR_STALE_WINDOW) != 0)
-#define RESIGN(header)                                 \
-       ((atomic_load_acquire(&(header)->attributes) & \
-         DNS_SLABHEADERATTR_RESIGN) != 0)
 #define OPTOUT(header)                                 \
        ((atomic_load_acquire(&(header)->attributes) & \
          DNS_SLABHEADERATTR_OPTOUT) != 0)
@@ -207,9 +203,6 @@ qp_triename(void *uctx, char *buf, size_t size) {
        snprintf(buf, size, "qpdb-lite");
 }
 
-static void
-free_gluetable(struct cds_wfs_stack *glue_stack);
-
 static void
 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG);
 static isc_result_t
@@ -287,8 +280,6 @@ typedef struct qpdb_dbiterator {
 
 static void
 free_qpdb(dns_qpdb_t *qpdb, bool log);
-static void
-setnsec3parameters(dns_db_t *db, dns_qpdb_version_t *version);
 
 /*%
  * 'init_count' is used to initialize 'newheader->count' which inturn
@@ -313,12 +304,6 @@ static atomic_uint_fast16_t init_count = 0;
  * Failure to follow this hierarchy can result in deadlock.
  */
 
-/*
- * Deleting Nodes
- *
- * For zone databases the node for the origin of the zone MUST NOT be deleted.
- */
-
 /*
  * DB Routines
  */
@@ -429,21 +414,6 @@ ttl_sooner(void *v1, void *v2) {
        return (h1->ttl < h2->ttl);
 }
 
-/*%
- * Return which RRset should be resigned sooner.  If the RRsets have the
- * same signing time, prefer the other RRset over the SOA RRset.
- */
-static bool
-resign_sooner(void *v1, void *v2) {
-       dns_slabheader_t *h1 = v1;
-       dns_slabheader_t *h2 = v2;
-
-       return (h1->resign < h2->resign ||
-               (h1->resign == h2->resign && h1->resign_lsb < h2->resign_lsb) ||
-               (h1->resign == h2->resign && h1->resign_lsb == h2->resign_lsb &&
-                h2->type == DNS_SIGTYPE(dns_rdatatype_soa)));
-}
-
 /*%
  * This function sets the heap index into the header.
  */
@@ -460,20 +430,6 @@ free_qpdb(dns_qpdb_t *qpdb, bool log) {
        char buf[DNS_NAME_FORMATSIZE];
        dns_qp_t **treep = NULL;
 
-       REQUIRE(qpdb->current_version != NULL || EMPTY(qpdb->open_versions));
-       REQUIRE(qpdb->future_version == NULL);
-
-       if (qpdb->current_version != NULL) {
-               isc_refcount_decrementz(&qpdb->current_version->references);
-
-               isc_refcount_destroy(&qpdb->current_version->references);
-               UNLINK(qpdb->open_versions, qpdb->current_version, link);
-               cds_wfs_destroy(&qpdb->current_version->glue_stack);
-               isc_rwlock_destroy(&qpdb->current_version->rwlock);
-               isc_mem_put(qpdb->common.mctx, qpdb->current_version,
-                           sizeof(*qpdb->current_version));
-       }
-
        /*
         * We assume the number of remaining dead nodes is reasonably small;
         * the overhead of unlinking all nodes here should be negligible.
@@ -615,15 +571,6 @@ dns__qpdb_destroy(dns_db_t *arg) {
                dns_db_detachnode((dns_db_t *)qpdb, &qpdb->nsnode);
        }
 
-       /*
-        * The current version's glue table needs to be freed early
-        * so the nodes are dereferenced before we check the active
-        * node count below.
-        */
-       if (qpdb->current_version != NULL) {
-               free_gluetable(&qpdb->current_version->glue_stack);
-       }
-
        /*
         * Even though there are no external direct references, there still
         * may be nodes in use.
@@ -662,169 +609,6 @@ dns__qpdb_destroy(dns_db_t *arg) {
        }
 }
 
-void
-dns__qpdb_currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       dns_qpdb_version_t *version = NULL;
-
-       REQUIRE(VALID_QPDB(qpdb));
-
-       RWLOCK(&qpdb->lock, isc_rwlocktype_read);
-       version = qpdb->current_version;
-       isc_refcount_increment(&version->references);
-       RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
-
-       *versionp = (dns_dbversion_t *)version;
-}
-
-static dns_qpdb_version_t *
-allocate_version(isc_mem_t *mctx, uint32_t serial, unsigned int references,
-                bool writer) {
-       dns_qpdb_version_t *version = isc_mem_get(mctx, sizeof(*version));
-       *version = (dns_qpdb_version_t){
-               .serial = serial,
-               .writer = writer,
-               .changed_list = ISC_LIST_INITIALIZER,
-               .resigned_list = ISC_LIST_INITIALIZER,
-               .link = ISC_LINK_INITIALIZER,
-       };
-
-       cds_wfs_init(&version->glue_stack);
-
-       isc_refcount_init(&version->references, references);
-
-       return (version);
-}
-
-isc_result_t
-dns__qpdb_newversion(dns_db_t *db, dns_dbversion_t **versionp) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       dns_qpdb_version_t *version = NULL;
-
-       REQUIRE(VALID_QPDB(qpdb));
-       REQUIRE(versionp != NULL && *versionp == NULL);
-       REQUIRE(qpdb->future_version == NULL);
-
-       RWLOCK(&qpdb->lock, isc_rwlocktype_write);
-       RUNTIME_CHECK(qpdb->next_serial != 0); /* XXX Error? */
-       version = allocate_version(qpdb->common.mctx, qpdb->next_serial, 1,
-                                  true);
-       version->qpdb = qpdb;
-       version->commit_ok = true;
-       version->secure = qpdb->current_version->secure;
-       version->havensec3 = qpdb->current_version->havensec3;
-       if (version->havensec3) {
-               version->flags = qpdb->current_version->flags;
-               version->iterations = qpdb->current_version->iterations;
-               version->hash = qpdb->current_version->hash;
-               version->salt_length = qpdb->current_version->salt_length;
-               memmove(version->salt, qpdb->current_version->salt,
-                       version->salt_length);
-       } else {
-               version->flags = 0;
-               version->iterations = 0;
-               version->hash = 0;
-               version->salt_length = 0;
-               memset(version->salt, 0, sizeof(version->salt));
-       }
-       isc_rwlock_init(&version->rwlock);
-       RWLOCK(&qpdb->current_version->rwlock, isc_rwlocktype_read);
-       version->records = qpdb->current_version->records;
-       version->xfrsize = qpdb->current_version->xfrsize;
-       RWUNLOCK(&qpdb->current_version->rwlock, isc_rwlocktype_read);
-       qpdb->next_serial++;
-       qpdb->future_version = version;
-       RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
-
-       *versionp = version;
-
-       return (ISC_R_SUCCESS);
-}
-
-void
-dns__qpdb_attachversion(dns_db_t *db, dns_dbversion_t *source,
-                       dns_dbversion_t **targetp) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       dns_qpdb_version_t *rbtversion = source;
-
-       REQUIRE(VALID_QPDB(qpdb));
-       INSIST(rbtversion != NULL && rbtversion->qpdb == qpdb);
-
-       isc_refcount_increment(&rbtversion->references);
-
-       *targetp = rbtversion;
-}
-
-static qpdb_changed_t *
-add_changed(dns_slabheader_t *header,
-           dns_qpdb_version_t *version DNS__DB_FLARG) {
-       qpdb_changed_t *changed = NULL;
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)header->db;
-
-       /*
-        * Caller must be holding the node lock if its reference must be
-        * protected by the lock.
-        */
-
-       changed = isc_mem_get(qpdb->common.mctx, sizeof(*changed));
-
-       RWLOCK(&qpdb->lock, isc_rwlocktype_write);
-
-       REQUIRE(version->writer);
-
-       if (changed != NULL) {
-               dns_qpdata_t *node = (dns_qpdata_t *)header->node;
-
-               dns__qpdb_newref(qpdb, node,
-                                isc_rwlocktype_none DNS__DB_FLARG_PASS);
-
-               changed->node = node;
-               changed->dirty = false;
-               ISC_LIST_INITANDAPPEND(version->changed_list, changed, link);
-       } else {
-               version->commit_ok = false;
-       }
-
-       RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
-
-       return (changed);
-}
-
-static void
-rollback_node(dns_qpdata_t *node, uint32_t serial) {
-       dns_slabheader_t *header = NULL, *dcurrent = NULL;
-       bool make_dirty = false;
-
-       /*
-        * Caller must hold the node lock.
-        */
-
-       /*
-        * We set the IGNORE attribute on rdatasets with serial number
-        * 'serial'.  When the reference count goes to zero, these rdatasets
-        * will be cleaned up; until that time, they will be ignored.
-        */
-       for (header = node->data; header != NULL; header = header->next) {
-               if (header->serial == serial) {
-                       DNS_SLABHEADER_SETATTR(header,
-                                              DNS_SLABHEADERATTR_IGNORE);
-                       make_dirty = true;
-               }
-               for (dcurrent = header->down; dcurrent != NULL;
-                    dcurrent = dcurrent->down)
-               {
-                       if (dcurrent->serial == serial) {
-                               DNS_SLABHEADER_SETATTR(
-                                       dcurrent, DNS_SLABHEADERATTR_IGNORE);
-                               make_dirty = true;
-                       }
-               }
-       }
-       if (make_dirty) {
-               node->dirty = 1;
-       }
-}
-
 void
 dns__qpdb_mark(dns_slabheader_t *header, uint_least16_t flag) {
        uint_least16_t attributes = atomic_load_acquire(&header->attributes);
@@ -902,138 +686,6 @@ clean_cache_node(dns_qpdb_t *qpdb, dns_qpdata_t *node) {
        node->dirty = 0;
 }
 
-static void
-clean_zone_node(dns_qpdata_t *node, uint32_t least_serial) {
-       dns_slabheader_t *current = NULL, *dcurrent = NULL;
-       dns_slabheader_t *down_next = NULL, *dparent = NULL;
-       dns_slabheader_t *top_prev = NULL, *top_next = NULL;
-       bool still_dirty = false;
-
-       /*
-        * Caller must be holding the node lock.
-        */
-       REQUIRE(least_serial != 0);
-
-       for (current = node->data; current != NULL; current = top_next) {
-               top_next = current->next;
-
-               /*
-                * First, we clean up any instances of multiple rdatasets
-                * with the same serial number, or that have the IGNORE
-                * attribute.
-                */
-               dparent = current;
-               for (dcurrent = current->down; dcurrent != NULL;
-                    dcurrent = down_next)
-               {
-                       down_next = dcurrent->down;
-                       INSIST(dcurrent->serial <= dparent->serial);
-                       if (dcurrent->serial == dparent->serial ||
-                           IGNORE(dcurrent))
-                       {
-                               if (down_next != NULL) {
-                                       down_next->next = dparent;
-                               }
-                               dparent->down = down_next;
-                               dns_slabheader_destroy(&dcurrent);
-                       } else {
-                               dparent = dcurrent;
-                       }
-               }
-
-               /*
-                * We've now eliminated all IGNORE datasets with the possible
-                * exception of current, which we now check.
-                */
-               if (IGNORE(current)) {
-                       down_next = current->down;
-                       if (down_next == NULL) {
-                               if (top_prev != NULL) {
-                                       top_prev->next = current->next;
-                               } else {
-                                       node->data = current->next;
-                               }
-                               dns_slabheader_destroy(&current);
-                               /*
-                                * current no longer exists, so we can
-                                * just continue with the loop.
-                                */
-                               continue;
-                       } else {
-                               /*
-                                * Pull up current->down, making it the new
-                                * current.
-                                */
-                               if (top_prev != NULL) {
-                                       top_prev->next = down_next;
-                               } else {
-                                       node->data = down_next;
-                               }
-                               down_next->next = top_next;
-                               dns_slabheader_destroy(&current);
-                               current = down_next;
-                       }
-               }
-
-               /*
-                * We now try to find the first down node less than the
-                * least serial.
-                */
-               dparent = current;
-               for (dcurrent = current->down; dcurrent != NULL;
-                    dcurrent = down_next)
-               {
-                       down_next = dcurrent->down;
-                       if (dcurrent->serial < least_serial) {
-                               break;
-                       }
-                       dparent = dcurrent;
-               }
-
-               /*
-                * If there is a such an rdataset, delete it and any older
-                * versions.
-                */
-               if (dcurrent != NULL) {
-                       do {
-                               down_next = dcurrent->down;
-                               INSIST(dcurrent->serial <= least_serial);
-                               dns_slabheader_destroy(&dcurrent);
-                               dcurrent = down_next;
-                       } while (dcurrent != NULL);
-                       dparent->down = NULL;
-               }
-
-               /*
-                * Note.  The serial number of 'current' might be less than
-                * least_serial too, but we cannot delete it because it is
-                * the most recent version, unless it is a NONEXISTENT
-                * rdataset.
-                */
-               if (current->down != NULL) {
-                       still_dirty = true;
-                       top_prev = current;
-               } else {
-                       /*
-                        * If this is a NONEXISTENT rdataset, we can delete it.
-                        */
-                       if (NONEXISTENT(current)) {
-                               if (top_prev != NULL) {
-                                       top_prev->next = current->next;
-                               } else {
-                                       node->data = current->next;
-                               }
-                               dns_slabheader_destroy(&current);
-                       } else {
-                               top_prev = current;
-                       }
-               }
-       }
-       if (!still_dirty) {
-               node->dirty = 0;
-       }
-}
-
 /*
  * tree_lock(write) must be held.
  */
@@ -1246,6 +898,7 @@ dns__qpdb_decref(dns_qpdb_t *qpdb, dns_qpdata_t *node, uint32_t least_serial,
        REQUIRE(*nlocktypep != isc_rwlocktype_none);
 
        UNUSED(pruning);
+       UNUSED(least_serial);
 
        nodelock = &qpdb->node_locks[bucket];
 
@@ -1302,20 +955,7 @@ dns__qpdb_decref(dns_qpdb_t *qpdb, dns_qpdata_t *node, uint32_t least_serial,
        INSIST(refs == 1);
 
        if (node->dirty) {
-               if (IS_CACHE(qpdb)) {
-                       clean_cache_node(qpdb, node);
-               } else {
-                       if (least_serial == 0) {
-                               /*
-                                * Caller doesn't know the least serial.
-                                * Get it.
-                                */
-                               RWLOCK(&qpdb->lock, isc_rwlocktype_read);
-                               least_serial = qpdb->least_serial;
-                               RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
-                       }
-                       clean_zone_node(node, least_serial);
-               }
+               clean_cache_node(qpdb, node);
        }
 
        /*
@@ -1391,506 +1031,16 @@ restore_locks:
        return (no_reference);
 }
 
-static void
-make_least_version(dns_qpdb_t *qpdb, dns_qpdb_version_t *version,
-                  qpdb_changedlist_t *cleanup_list) {
-       /*
-        * Caller must be holding the database lock.
-        */
-
-       qpdb->least_serial = version->serial;
-       *cleanup_list = version->changed_list;
-       ISC_LIST_INIT(version->changed_list);
-}
-
-static void
-cleanup_nondirty(dns_qpdb_version_t *version,
-                qpdb_changedlist_t *cleanup_list) {
-       qpdb_changed_t *changed = NULL, *next_changed = NULL;
-
-       /*
-        * If the changed record is dirty, then
-        * an update created multiple versions of
-        * a given rdataset.  We keep this list
-        * until we're the least open version, at
-        * which point it's safe to get rid of any
-        * older versions.
-        *
-        * If the changed record isn't dirty, then
-        * we don't need it anymore since we're
-        * committing and not rolling back.
-        *
-        * The caller must be holding the database lock.
-        */
-       for (changed = HEAD(version->changed_list); changed != NULL;
-            changed = next_changed)
-       {
-               next_changed = NEXT(changed, link);
-               if (!changed->dirty) {
-                       UNLINK(version->changed_list, changed, link);
-                       APPEND(*cleanup_list, changed, link);
-               }
-       }
-}
-
-void
-dns__qpdb_setsecure(dns_db_t *db, dns_qpdb_version_t *version,
-                   dns_dbnode_t *origin) {
-       dns_rdataset_t keyset;
-       dns_rdataset_t nsecset, signsecset;
-       bool haszonekey = false;
-       bool hasnsec = false;
-       isc_result_t result;
-
-       dns_rdataset_init(&keyset);
-       result = dns_db_findrdataset(db, origin, version, dns_rdatatype_dnskey,
-                                    0, 0, &keyset, NULL);
-       if (result == ISC_R_SUCCESS) {
-               result = dns_rdataset_first(&keyset);
-               while (result == ISC_R_SUCCESS) {
-                       dns_rdata_t keyrdata = DNS_RDATA_INIT;
-                       dns_rdataset_current(&keyset, &keyrdata);
-                       if (dns_zonekey_iszonekey(&keyrdata)) {
-                               haszonekey = true;
-                               break;
-                       }
-                       result = dns_rdataset_next(&keyset);
-               }
-               dns_rdataset_disassociate(&keyset);
-       }
-       if (!haszonekey) {
-               version->secure = false;
-               version->havensec3 = false;
-               return;
-       }
-
-       dns_rdataset_init(&nsecset);
-       dns_rdataset_init(&signsecset);
-       result = dns_db_findrdataset(db, origin, version, dns_rdatatype_nsec, 0,
-                                    0, &nsecset, &signsecset);
-       if (result == ISC_R_SUCCESS) {
-               if (dns_rdataset_isassociated(&signsecset)) {
-                       hasnsec = true;
-                       dns_rdataset_disassociate(&signsecset);
-               }
-               dns_rdataset_disassociate(&nsecset);
-       }
-
-       setnsec3parameters(db, version);
-
-       /*
-        * Do we have a valid NSEC/NSEC3 chain?
-        */
-       if (version->havensec3 || hasnsec) {
-               version->secure = true;
-       } else {
-               version->secure = false;
-       }
-}
-
-/*%<
- * Walk the origin node looking for NSEC3PARAM records.
- * Cache the nsec3 parameters.
- */
-static void
-setnsec3parameters(dns_db_t *db, dns_qpdb_version_t *version) {
-       dns_qpdata_t *node = NULL;
-       dns_rdata_nsec3param_t nsec3param;
-       dns_rdata_t rdata = DNS_RDATA_INIT;
-       isc_region_t region;
-       isc_result_t result;
-       dns_slabheader_t *header = NULL, *header_next = NULL;
-       unsigned char *raw; /* RDATASLAB */
-       unsigned int count, length;
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
-       isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-       TREE_RDLOCK(&qpdb->tree_lock, &tlocktype);
-       version->havensec3 = false;
-       node = qpdb->origin_node;
-       NODE_RDLOCK(&(qpdb->node_locks[node->locknum].lock), &nlocktype);
-       for (header = node->data; header != NULL; header = header_next) {
-               header_next = header->next;
-               do {
-                       if (header->serial <= version->serial &&
-                           !IGNORE(header))
-                       {
-                               if (NONEXISTENT(header)) {
-                                       header = NULL;
-                               }
-                               break;
-                       } else {
-                               header = header->down;
-                       }
-               } while (header != NULL);
-
-               if (header != NULL &&
-                   (header->type == dns_rdatatype_nsec3param))
-               {
-                       /*
-                        * Find A NSEC3PARAM with a supported algorithm.
-                        */
-                       raw = dns_slabheader_raw(header);
-                       count = raw[0] * 256 + raw[1]; /* count */
-                       raw += DNS_RDATASET_COUNT + DNS_RDATASET_LENGTH;
-                       while (count-- > 0U) {
-                               length = raw[0] * 256 + raw[1];
-                               raw += DNS_RDATASET_ORDER + DNS_RDATASET_LENGTH;
-                               region.base = raw;
-                               region.length = length;
-                               raw += length;
-                               dns_rdata_fromregion(
-                                       &rdata, qpdb->common.rdclass,
-                                       dns_rdatatype_nsec3param, &region);
-                               result = dns_rdata_tostruct(&rdata, &nsec3param,
-                                                           NULL);
-                               INSIST(result == ISC_R_SUCCESS);
-                               dns_rdata_reset(&rdata);
-
-                               if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG &&
-                                   !dns_nsec3_supportedhash(nsec3param.hash))
-                               {
-                                       continue;
-                               }
-
-                               if (nsec3param.flags != 0) {
-                                       continue;
-                               }
-
-                               memmove(version->salt, nsec3param.salt,
-                                       nsec3param.salt_length);
-                               version->hash = nsec3param.hash;
-                               version->salt_length = nsec3param.salt_length;
-                               version->iterations = nsec3param.iterations;
-                               version->flags = nsec3param.flags;
-                               version->havensec3 = true;
-                               /*
-                                * Look for a better algorithm than the
-                                * unknown test algorithm.
-                                */
-                               if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG) {
-                                       goto unlock;
-                               }
-                       }
-               }
-       }
-unlock:
-       NODE_UNLOCK(&(qpdb->node_locks[node->locknum].lock), &nlocktype);
-       TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
-}
-
-static void
-cleanup_dead_nodes_callback(void *arg) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)arg;
-       bool again = false;
-       unsigned int locknum;
-       isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
-       isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-       TREE_WRLOCK(&qpdb->tree_lock, &tlocktype);
-       for (locknum = 0; locknum < qpdb->node_lock_count; locknum++) {
-               NODE_WRLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
-               cleanup_dead_nodes(qpdb, locknum DNS__DB_FILELINE);
-               if (ISC_LIST_HEAD(qpdb->deadnodes[locknum]) != NULL) {
-                       again = true;
-               }
-               NODE_UNLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
-       }
-       TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
-       if (again) {
-               isc_async_run(qpdb->loop, cleanup_dead_nodes_callback, qpdb);
-       } else {
-               dns_db_detach((dns_db_t **)&qpdb);
-       }
-}
-
-void
-dns__qpdb_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
-                      bool commit DNS__DB_FLARG) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       dns_qpdb_version_t *version = NULL, *cleanup_version = NULL;
-       dns_qpdb_version_t *least_greater = NULL;
-       bool rollback = false;
-       qpdb_changedlist_t cleanup_list;
-       dns_slabheaderlist_t resigned_list;
-       qpdb_changed_t *changed = NULL, *next_changed = NULL;
-       uint32_t serial, least_serial;
-       dns_qpdata_t *qpnode = NULL;
-       dns_slabheader_t *header = NULL;
-
-       REQUIRE(VALID_QPDB(qpdb));
-       version = (dns_qpdb_version_t *)*versionp;
-       INSIST(version->qpdb == qpdb);
-
-       ISC_LIST_INIT(cleanup_list);
-       ISC_LIST_INIT(resigned_list);
-
-       if (isc_refcount_decrement(&version->references) > 1) {
-               /* typical and easy case first */
-               if (commit) {
-                       RWLOCK(&qpdb->lock, isc_rwlocktype_read);
-                       INSIST(!version->writer);
-                       RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
-               }
-               goto end;
-       }
-
-       /*
-        * Update the zone's secure status in version before making
-        * it the current version.
-        */
-       if (version->writer && commit && !IS_CACHE(qpdb)) {
-               dns__qpdb_setsecure(db, version, qpdb->origin_node);
-       }
-
-       RWLOCK(&qpdb->lock, isc_rwlocktype_write);
-       serial = version->serial;
-       if (version->writer) {
-               if (commit) {
-                       unsigned int cur_ref;
-                       dns_qpdb_version_t *cur_version = NULL;
-
-                       INSIST(version->commit_ok);
-                       INSIST(version == qpdb->future_version);
-                       /*
-                        * The current version is going to be replaced.
-                        * Release the (likely last) reference to it from the
-                        * DB itself and unlink it from the open list.
-                        */
-                       cur_version = qpdb->current_version;
-                       cur_ref = isc_refcount_decrement(
-                               &cur_version->references);
-                       if (cur_ref == 1) {
-                               (void)isc_refcount_current(
-                                       &cur_version->references);
-                               if (cur_version->serial == qpdb->least_serial) {
-                                       INSIST(EMPTY(
-                                               cur_version->changed_list));
-                               }
-                               UNLINK(qpdb->open_versions, cur_version, link);
-                       }
-                       if (EMPTY(qpdb->open_versions)) {
-                               /*
-                                * We're going to become the least open
-                                * version.
-                                */
-                               make_least_version(qpdb, version,
-                                                  &cleanup_list);
-                       } else {
-                               /*
-                                * Some other open version is the
-                                * least version.  We can't cleanup
-                                * records that were changed in this
-                                * version because the older versions
-                                * may still be in use by an open
-                                * version.
-                                *
-                                * We can, however, discard the
-                                * changed records for things that
-                                * we've added that didn't exist in
-                                * prior versions.
-                                */
-                               cleanup_nondirty(version, &cleanup_list);
-                       }
-                       /*
-                        * If the (soon to be former) current version
-                        * isn't being used by anyone, we can clean
-                        * it up.
-                        */
-                       if (cur_ref == 1) {
-                               cleanup_version = cur_version;
-                               APPENDLIST(version->changed_list,
-                                          cleanup_version->changed_list, link);
-                       }
-                       /*
-                        * Become the current version.
-                        */
-                       version->writer = false;
-                       qpdb->current_version = version;
-                       qpdb->current_serial = version->serial;
-                       qpdb->future_version = NULL;
-
-                       /*
-                        * Keep the current version in the open list, and
-                        * gain a reference for the DB itself (see the DB
-                        * creation function below).  This must be the only
-                        * case where we need to increment the counter from
-                        * zero and need to use isc_refcount_increment0().
-                        */
-                       INSIST(isc_refcount_increment0(&version->references) ==
-                              0);
-                       PREPEND(qpdb->open_versions, qpdb->current_version,
-                               link);
-                       resigned_list = version->resigned_list;
-                       ISC_LIST_INIT(version->resigned_list);
-               } else {
-                       /*
-                        * We're rolling back this transaction.
-                        */
-                       cleanup_list = version->changed_list;
-                       ISC_LIST_INIT(version->changed_list);
-                       resigned_list = version->resigned_list;
-                       ISC_LIST_INIT(version->resigned_list);
-                       rollback = true;
-                       cleanup_version = version;
-                       qpdb->future_version = NULL;
-               }
-       } else {
-               if (version != qpdb->current_version) {
-                       /*
-                        * There are no external or internal references
-                        * to this version and it can be cleaned up.
-                        */
-                       cleanup_version = version;
-
-                       /*
-                        * Find the version with the least serial
-                        * number greater than ours.
-                        */
-                       least_greater = PREV(version, link);
-                       if (least_greater == NULL) {
-                               least_greater = qpdb->current_version;
-                       }
-
-                       INSIST(version->serial < least_greater->serial);
-                       /*
-                        * Is this the least open version?
-                        */
-                       if (version->serial == qpdb->least_serial) {
-                               /*
-                                * Yes.  Install the new least open
-                                * version.
-                                */
-                               make_least_version(qpdb, least_greater,
-                                                  &cleanup_list);
-                       } else {
-                               /*
-                                * Add any unexecuted cleanups to
-                                * those of the least greater version.
-                                */
-                               APPENDLIST(least_greater->changed_list,
-                                          version->changed_list, link);
-                       }
-               } else if (version->serial == qpdb->least_serial) {
-                       INSIST(EMPTY(version->changed_list));
-               }
-               UNLINK(qpdb->open_versions, version, link);
-       }
-       least_serial = qpdb->least_serial;
-       RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
-
-       if (cleanup_version != NULL) {
-               isc_refcount_destroy(&cleanup_version->references);
-               INSIST(EMPTY(cleanup_version->changed_list));
-               free_gluetable(&cleanup_version->glue_stack);
-               cds_wfs_destroy(&cleanup_version->glue_stack);
-               isc_rwlock_destroy(&cleanup_version->rwlock);
-               isc_mem_put(qpdb->common.mctx, cleanup_version,
-                           sizeof(*cleanup_version));
-       }
-
-       /*
-        * Commit/rollback re-signed headers.
-        */
-       for (header = HEAD(resigned_list); header != NULL;
-            header = HEAD(resigned_list))
-       {
-               isc_rwlock_t *lock = NULL;
-               isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
-               isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-               ISC_LIST_UNLINK(resigned_list, header, link);
-
-               lock = &qpdb->node_locks[QPDB_HEADERNODE(header)->locknum].lock;
-               NODE_WRLOCK(lock, &nlocktype);
-               if (rollback && !IGNORE(header)) {
-                       dns__qpzone_resigninsert(
-                               qpdb, QPDB_HEADERNODE(header)->locknum, header);
-               }
-               dns__qpdb_decref(qpdb, QPDB_HEADERNODE(header), least_serial,
-                                &nlocktype, &tlocktype, true,
-                                false DNS__DB_FLARG_PASS);
-               NODE_UNLOCK(lock, &nlocktype);
-               INSIST(tlocktype == isc_rwlocktype_none);
-       }
-
-       if (!EMPTY(cleanup_list)) {
-               isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
-
-               if (qpdb->loop == NULL) {
-                       /*
-                        * We acquire a tree write lock here in order to make
-                        * sure that stale nodes will be removed in
-                        * dns__qpdb_decref().  If we didn't have the lock,
-                        * those nodes could miss the chance to be removed
-                        * until the server stops.  The write lock is
-                        * expensive, but this should be rare enough
-                        * to justify the cost.
-                        */
-                       TREE_WRLOCK(&qpdb->tree_lock, &tlocktype);
-               }
-
-               for (changed = HEAD(cleanup_list); changed != NULL;
-                    changed = next_changed)
-               {
-                       isc_rwlock_t *lock = NULL;
-                       isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-                       next_changed = NEXT(changed, link);
-                       qpnode = changed->node;
-                       lock = &qpdb->node_locks[qpnode->locknum].lock;
-
-                       NODE_WRLOCK(lock, &nlocktype);
-                       /*
-                        * This is a good opportunity to purge any dead nodes,
-                        * so use it.
-                        */
-                       if (qpdb->loop == NULL) {
-                               cleanup_dead_nodes(
-                                       qpdb,
-                                       qpnode->locknum DNS__DB_FLARG_PASS);
-                       }
-
-                       if (rollback) {
-                               rollback_node(qpnode, serial);
-                       }
-                       dns__qpdb_decref(qpdb, qpnode, least_serial, &nlocktype,
-                                        &tlocktype, true,
-                                        false DNS__DB_FILELINE);
-
-                       NODE_UNLOCK(lock, &nlocktype);
-
-                       isc_mem_put(qpdb->common.mctx, changed,
-                                   sizeof(*changed));
-               }
-               if (qpdb->loop != NULL) {
-                       isc_refcount_increment(&qpdb->common.references);
-                       isc_async_run(qpdb->loop, cleanup_dead_nodes_callback,
-                                     qpdb);
-               } else {
-                       TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
-               }
-
-               INSIST(tlocktype == isc_rwlocktype_none);
-       }
-
-end:
-       *versionp = NULL;
-}
-
 isc_result_t
 dns__qpdb_findnodeintree(dns_qpdb_t *qpdb, dns_qp_t *tree,
                         const dns_name_t *name, bool create,
                         dns_dbnode_t **nodep DNS__DB_FLARG) {
        dns_qpdata_t *node = NULL;
-       dns_name_t nodename;
        isc_result_t result;
        isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
 
-       INSIST(tree == qpdb->tree || tree == qpdb->nsec3);
+       REQUIRE(tree == qpdb->tree || tree == qpdb->nsec3);
 
-       dns_name_init(&nodename, NULL);
        TREE_RDLOCK(&qpdb->tree_lock, &tlocktype);
        result = dns_qp_lookup(tree, name, NULL, NULL, NULL, (void **)&node,
                               NULL);
@@ -1914,17 +1064,6 @@ dns__qpdb_findnodeintree(dns_qpdb_t *qpdb, dns_qp_t *tree,
                        dns_qpdata_unref(node);
                }
 
-               if (tree == qpdb->tree) {
-                       dns__qpzone_addwildcards(qpdb, name, true);
-
-                       if (dns_name_iswildcard(name)) {
-                               result = dns__qpzone_wildcardmagic(qpdb, name,
-                                                                  true);
-                               if (result != ISC_R_SUCCESS) {
-                                       goto unlock;
-                               }
-                       }
-               }
                if (tree == qpdb->nsec3) {
                        node->nsec = DNS_DB_NSEC_NSEC3;
                }
@@ -2007,6 +1146,7 @@ dns__qpdb_bindrdataset(dns_qpdb_t *qpdb, dns_qpdata_t *node,
        rdataset->covers = DNS_TYPEPAIR_COVERS(header->type);
        rdataset->ttl = header->ttl - now;
        rdataset->trust = header->trust;
+       rdataset->resign = 0;
 
        if (NEGATIVE(header)) {
                rdataset->attributes |= DNS_RDATASETATTR_NEGATIVE;
@@ -2032,7 +1172,7 @@ dns__qpdb_bindrdataset(dns_qpdb_t *qpdb, dns_qpdata_t *node,
                        rdataset->attributes |= DNS_RDATASETATTR_STALE_WINDOW;
                }
                rdataset->attributes |= DNS_RDATASETATTR_STALE;
-       } else if (IS_CACHE(qpdb) && !ACTIVE(header, now)) {
+       } else if (!ACTIVE(header, now)) {
                rdataset->attributes |= DNS_RDATASETATTR_ANCIENT;
                rdataset->ttl = header->ttl;
        }
@@ -2056,16 +1196,6 @@ dns__qpdb_bindrdataset(dns_qpdb_t *qpdb, dns_qpdata_t *node,
        if (header->closest != NULL) {
                rdataset->attributes |= DNS_RDATASETATTR_CLOSEST;
        }
-
-       /*
-        * Copy out re-signing information.
-        */
-       if (RESIGN(header)) {
-               rdataset->attributes |= DNS_RDATASETATTR_RESIGN;
-               rdataset->resign = (header->resign << 1) | header->resign_lsb;
-       } else {
-               rdataset->resign = 0;
-       }
 }
 
 void
@@ -2190,35 +1320,23 @@ dns__qpdb_allrdatasets(dns_db_t *db, dns_dbnode_t *node,
                       dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) {
        dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
        dns_qpdata_t *qpnode = (dns_qpdata_t *)node;
-       dns_qpdb_version_t *rbtversion = version;
        qpdb_rdatasetiter_t *iterator = NULL;
 
        REQUIRE(VALID_QPDB(qpdb));
 
-       iterator = isc_mem_get(qpdb->common.mctx, sizeof(*iterator));
+       UNUSED(version);
 
-       if ((db->attributes & DNS_DBATTR_CACHE) == 0) {
-               now = 0;
-               if (rbtversion == NULL) {
-                       dns__qpdb_currentversion(
-                               db, (dns_dbversion_t **)(void *)(&rbtversion));
-               } else {
-                       INSIST(rbtversion->qpdb == qpdb);
+       iterator = isc_mem_get(qpdb->common.mctx, sizeof(*iterator));
 
-                       (void)isc_refcount_increment(&rbtversion->references);
-               }
-       } else {
-               if (now == 0) {
-                       now = isc_stdtime_now();
-               }
-               rbtversion = NULL;
+       if (now == 0) {
+               now = isc_stdtime_now();
        }
 
        iterator->common.magic = DNS_RDATASETITER_MAGIC;
        iterator->common.methods = &rdatasetiter_methods;
        iterator->common.db = db;
        iterator->common.node = node;
-       iterator->common.version = (dns_dbversion_t *)rbtversion;
+       iterator->common.version = NULL;
        iterator->common.options = options;
        iterator->common.now = now;
        iterator->current = NULL;
@@ -2230,168 +1348,30 @@ dns__qpdb_allrdatasets(dns_db_t *db, dns_dbnode_t *node,
        return (ISC_R_SUCCESS);
 }
 
-static bool
-cname_and_other_data(dns_qpdata_t *node, uint32_t serial) {
-       dns_slabheader_t *header = NULL, *header_next = NULL;
-       bool cname = false, other_data = false;
-       dns_rdatatype_t rdtype;
-
-       /*
-        * The caller must hold the node lock.
-        */
-
-       /*
-        * Look for CNAME and "other data" rdatasets active in our version.
-        */
-       for (header = node->data; header != NULL; header = header_next) {
-               header_next = header->next;
-               if (!prio_type(header->type)) {
-                       /*
-                        * CNAME is in the priority list, so if we are done
-                        * with the priority list, we know there will not be
-                        * CNAME, so we are safe to skip the rest of the types.
-                        */
-                       return (false);
-               }
-               if (header->type == dns_rdatatype_cname) {
-                       /*
-                        * Look for an active extant CNAME.
-                        */
-                       do {
-                               if (header->serial <= serial && !IGNORE(header))
-                               {
-                                       /*
-                                        * Is this a "this rdataset doesn't
-                                        * exist" record?
-                                        */
-                                       if (NONEXISTENT(header)) {
-                                               header = NULL;
-                                       }
-                                       break;
-                               } else {
-                                       header = header->down;
-                               }
-                       } while (header != NULL);
-                       if (header != NULL) {
-                               cname = true;
-                       }
-               } else {
-                       /*
-                        * Look for active extant "other data".
-                        *
-                        * "Other data" is any rdataset whose type is not
-                        * KEY, NSEC, SIG or RRSIG.
-                        */
-                       rdtype = DNS_TYPEPAIR_TYPE(header->type);
-                       if (rdtype != dns_rdatatype_key &&
-                           rdtype != dns_rdatatype_sig &&
-                           rdtype != dns_rdatatype_nsec &&
-                           rdtype != dns_rdatatype_rrsig)
-                       {
-                               /*
-                                * Is it active and extant?
-                                */
-                               do {
-                                       if (header->serial <= serial &&
-                                           !IGNORE(header))
-                                       {
-                                               /*
-                                                * Is this a "this rdataset
-                                                * doesn't exist" record?
-                                                */
-                                               if (NONEXISTENT(header)) {
-                                                       header = NULL;
-                                               }
-                                               break;
-                                       } else {
-                                               header = header->down;
-                                       }
-                               } while (header != NULL);
-                               if (header != NULL) {
-                                       other_data = true;
-                               }
-                       }
-               }
-               if (cname && other_data) {
-                       return (true);
-               }
-       }
-
-       return (false);
-}
-
-static uint64_t
-recordsize(dns_slabheader_t *header, unsigned int namelen) {
-       return (dns_rdataslab_rdatasize((unsigned char *)header,
-                                       sizeof(*header)) +
-               sizeof(dns_ttl_t) + sizeof(dns_rdatatype_t) +
-               sizeof(dns_rdataclass_t) + namelen);
-}
-
-static void
-update_recordsandxfrsize(bool add, dns_qpdb_version_t *rbtversion,
-                        dns_slabheader_t *header, unsigned int namelen) {
-       unsigned char *hdr = (unsigned char *)header;
-       size_t hdrsize = sizeof(*header);
-
-       RWLOCK(&rbtversion->rwlock, isc_rwlocktype_write);
-       if (add) {
-               rbtversion->records += dns_rdataslab_count(hdr, hdrsize);
-               rbtversion->xfrsize += recordsize(header, namelen);
-       } else {
-               rbtversion->records -= dns_rdataslab_count(hdr, hdrsize);
-               rbtversion->xfrsize -= recordsize(header, namelen);
-       }
-       RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_write);
-}
-
 isc_result_t
 dns__qpdb_add(dns_qpdb_t *qpdb, dns_qpdata_t *qpnode,
-             const dns_name_t *nodename, dns_qpdb_version_t *rbtversion,
+             const dns_name_t *nodename ISC_ATTR_UNUSED,
              dns_slabheader_t *newheader, unsigned int options, bool loading,
              dns_rdataset_t *addedrdataset, isc_stdtime_t now DNS__DB_FLARG) {
        qpdb_changed_t *changed = NULL;
        dns_slabheader_t *topheader = NULL, *topheader_prev = NULL;
        dns_slabheader_t *header = NULL, *sigheader = NULL;
        dns_slabheader_t *prioheader = NULL;
-       unsigned char *merged = NULL;
-       isc_result_t result;
        bool header_nx;
        bool newheader_nx;
-       bool merge;
        dns_rdatatype_t rdtype, covers;
        dns_typepair_t negtype = 0, sigtype;
        dns_trust_t trust;
        int idx;
 
-       if ((options & DNS_DBADD_MERGE) != 0) {
-               REQUIRE(rbtversion != NULL);
-               merge = true;
-       } else {
-               merge = false;
-       }
-
        if ((options & DNS_DBADD_FORCE) != 0) {
                trust = dns_trust_ultimate;
        } else {
                trust = newheader->trust;
        }
 
-       if (rbtversion != NULL && !loading) {
-               /*
-                * We always add a changed record, even if no changes end up
-                * being made to this node, because it's harmless and
-                * simplifies the code.
-                */
-               changed = add_changed(newheader, rbtversion DNS__DB_FLARG_PASS);
-               if (changed == NULL) {
-                       dns_slabheader_destroy(&newheader);
-                       return (ISC_R_NOMEMORY);
-               }
-       }
-
        newheader_nx = NONEXISTENT(newheader) ? true : false;
-       if (rbtversion == NULL && !newheader_nx) {
+       if (!newheader_nx) {
                rdtype = DNS_TYPEPAIR_TYPE(newheader->type);
                covers = DNS_TYPEPAIR_COVERS(newheader->type);
                sigtype = DNS_SIGTYPE(covers);
@@ -2525,8 +1505,7 @@ find_header:
                 * data will supersede it below. Unclear what the best
                 * policy is here.
                 */
-               if (rbtversion == NULL && trust < header->trust &&
-                   (ACTIVE(header, now) || header_nx))
+               if (trust < header->trust && (ACTIVE(header, now) || header_nx))
                {
                        dns_slabheader_destroy(&newheader);
                        if (addedrdataset != NULL) {
@@ -2538,74 +1517,6 @@ find_header:
                        return (DNS_R_UNCHANGED);
                }
 
-               /*
-                * Don't merge if a nonexistent rdataset is involved.
-                */
-               if (merge && (header_nx || newheader_nx)) {
-                       merge = false;
-               }
-
-               /*
-                * If 'merge' is true, we'll try to create a new rdataset
-                * that is the union of 'newheader' and 'header'.
-                */
-               if (merge) {
-                       unsigned int flags = 0;
-                       INSIST(rbtversion->serial >= header->serial);
-                       merged = NULL;
-                       result = ISC_R_SUCCESS;
-
-                       if ((options & DNS_DBADD_EXACT) != 0) {
-                               flags |= DNS_RDATASLAB_EXACT;
-                       }
-                       /*
-                        * TTL use here is irrelevant to the cache;
-                        * merge is only done with zonedbs.
-                        */
-                       if ((options & DNS_DBADD_EXACTTTL) != 0 &&
-                           newheader->ttl != header->ttl)
-                       {
-                               result = DNS_R_NOTEXACT;
-                       } else if (newheader->ttl != header->ttl) {
-                               flags |= DNS_RDATASLAB_FORCE;
-                       }
-                       if (result == ISC_R_SUCCESS) {
-                               result = dns_rdataslab_merge(
-                                       (unsigned char *)header,
-                                       (unsigned char *)newheader,
-                                       (unsigned int)(sizeof(*newheader)),
-                                       qpdb->common.mctx, qpdb->common.rdclass,
-                                       (dns_rdatatype_t)header->type, flags,
-                                       &merged);
-                       }
-                       if (result == ISC_R_SUCCESS) {
-                               /*
-                                * If 'header' has the same serial number as
-                                * we do, we could clean it up now if we knew
-                                * that our caller had no references to it.
-                                * We don't know this, however, so we leave it
-                                * alone.  It will get cleaned up when
-                                * clean_zone_node() runs.
-                                */
-                               dns_slabheader_destroy(&newheader);
-                               newheader = (dns_slabheader_t *)merged;
-                               dns_slabheader_reset(newheader,
-                                                    (dns_db_t *)qpdb,
-                                                    (dns_dbnode_t *)qpnode);
-                               dns_slabheader_copycase(newheader, header);
-                               if (loading && RESIGN(newheader) &&
-                                   RESIGN(header) &&
-                                   resign_sooner(header, newheader))
-                               {
-                                       newheader->resign = header->resign;
-                                       newheader->resign_lsb =
-                                               header->resign_lsb;
-                               }
-                       } else {
-                               dns_slabheader_destroy(&newheader);
-                               return (result);
-                       }
-               }
                /*
                 * Don't replace existing NS, A and AAAA RRsets in the
                 * cache if they are already exist. This prevents named
@@ -2614,9 +1525,9 @@ find_header:
                 * special to be done w.r.t stale data; it gets replaced
                 * normally further down.
                 */
-               if (IS_CACHE(qpdb) && ACTIVE(header, now) &&
-                   header->type == dns_rdatatype_ns && !header_nx &&
-                   !newheader_nx && header->trust >= newheader->trust &&
+               if (ACTIVE(header, now) && header->type == dns_rdatatype_ns &&
+                   !header_nx && !newheader_nx &&
+                   header->trust >= newheader->trust &&
                    dns_rdataslab_equalx((unsigned char *)header,
                                         (unsigned char *)newheader,
                                         (unsigned int)(sizeof(*newheader)),
@@ -2668,15 +1579,15 @@ find_header:
                 * to be no more than the current NS RRset's TTL.  This
                 * ensures the delegations that are withdrawn are honoured.
                 */
-               if (IS_CACHE(qpdb) && ACTIVE(header, now) &&
-                   header->type == dns_rdatatype_ns && !header_nx &&
-                   !newheader_nx && header->trust <= newheader->trust)
+               if (ACTIVE(header, now) && header->type == dns_rdatatype_ns &&
+                   !header_nx && !newheader_nx &&
+                   header->trust <= newheader->trust)
                {
                        if (newheader->ttl > header->ttl) {
                                newheader->ttl = header->ttl;
                        }
                }
-               if (IS_CACHE(qpdb) && ACTIVE(header, now) &&
+               if (ACTIVE(header, now) &&
                    (options & DNS_DBADD_PREFETCH) == 0 &&
                    (header->type == dns_rdatatype_a ||
                     header->type == dns_rdatatype_aaaa ||
@@ -2727,32 +1638,21 @@ find_header:
                        }
                        return (ISC_R_SUCCESS);
                }
-               INSIST(rbtversion == NULL ||
-                      rbtversion->serial >= topheader->serial);
+
                if (loading) {
                        newheader->down = NULL;
                        idx = QPDB_HEADERNODE(newheader)->locknum;
-                       if (IS_CACHE(qpdb)) {
-                               if (ZEROTTL(newheader)) {
-                                       newheader->last_used = qpdb->last_used +
-                                                              1;
-                                       ISC_LIST_APPEND(qpdb->lru[idx],
-                                                       newheader, link);
-                               } else {
-                                       ISC_LIST_PREPEND(qpdb->lru[idx],
-                                                        newheader, link);
-                               }
-                               INSIST(qpdb->heaps != NULL);
-                               isc_heap_insert(qpdb->heaps[idx], newheader);
-                               newheader->heap = qpdb->heaps[idx];
-                       } else if (RESIGN(newheader)) {
-                               dns__qpzone_resigninsert(qpdb, idx, newheader);
-                               /*
-                                * Don't call resigndelete, we don't need
-                                * to reverse the delete.  The free_slabheader
-                                * call below will clean up the heap entry.
-                                */
+                       if (ZEROTTL(newheader)) {
+                               newheader->last_used = qpdb->last_used + 1;
+                               ISC_LIST_APPEND(qpdb->lru[idx], newheader,
+                                               link);
+                       } else {
+                               ISC_LIST_PREPEND(qpdb->lru[idx], newheader,
+                                                link);
                        }
+                       INSIST(qpdb->heaps != NULL);
+                       isc_heap_insert(qpdb->heaps[idx], newheader);
+                       newheader->heap = qpdb->heaps[idx];
 
                        /*
                         * There are no other references to 'header' when
@@ -2766,32 +1666,19 @@ find_header:
                                qpnode->data = newheader;
                        }
                        newheader->next = topheader->next;
-                       if (rbtversion != NULL && !header_nx) {
-                               update_recordsandxfrsize(false, rbtversion,
-                                                        header,
-                                                        nodename->length);
-                       }
                        dns_slabheader_destroy(&header);
                } else {
                        idx = QPDB_HEADERNODE(newheader)->locknum;
-                       if (IS_CACHE(qpdb)) {
-                               INSIST(qpdb->heaps != NULL);
-                               isc_heap_insert(qpdb->heaps[idx], newheader);
-                               newheader->heap = qpdb->heaps[idx];
-                               if (ZEROTTL(newheader)) {
-                                       newheader->last_used = qpdb->last_used +
-                                                              1;
-                                       ISC_LIST_APPEND(qpdb->lru[idx],
-                                                       newheader, link);
-                               } else {
-                                       ISC_LIST_PREPEND(qpdb->lru[idx],
-                                                        newheader, link);
-                               }
-                       } else if (RESIGN(newheader)) {
-                               dns__qpzone_resigninsert(qpdb, idx, newheader);
-                               dns__qpzone_resigndelete(
-                                       qpdb, rbtversion,
-                                       header DNS__DB_FLARG_PASS);
+                       INSIST(qpdb->heaps != NULL);
+                       isc_heap_insert(qpdb->heaps[idx], newheader);
+                       newheader->heap = qpdb->heaps[idx];
+                       if (ZEROTTL(newheader)) {
+                               newheader->last_used = qpdb->last_used + 1;
+                               ISC_LIST_APPEND(qpdb->lru[idx], newheader,
+                                               link);
+                       } else {
+                               ISC_LIST_PREPEND(qpdb->lru[idx], newheader,
+                                                link);
                        }
                        if (topheader_prev != NULL) {
                                topheader_prev->next = newheader;
@@ -2805,16 +1692,9 @@ find_header:
                        if (changed != NULL) {
                                changed->dirty = true;
                        }
-                       if (rbtversion == NULL) {
-                               mark_ancient(header);
-                               if (sigheader != NULL) {
-                                       mark_ancient(sigheader);
-                               }
-                       }
-                       if (rbtversion != NULL && !header_nx) {
-                               update_recordsandxfrsize(false, rbtversion,
-                                                        header,
-                                                        nodename->length);
+                       mark_ancient(header);
+                       if (sigheader != NULL) {
+                               mark_ancient(sigheader);
                        }
                }
        } else {
@@ -2832,20 +1712,12 @@ find_header:
                }
 
                idx = QPDB_HEADERNODE(newheader)->locknum;
-               if (IS_CACHE(qpdb)) {
-                       isc_heap_insert(qpdb->heaps[idx], newheader);
-                       newheader->heap = qpdb->heaps[idx];
-                       if (ZEROTTL(newheader)) {
-                               ISC_LIST_APPEND(qpdb->lru[idx], newheader,
-                                               link);
-                       } else {
-                               ISC_LIST_PREPEND(qpdb->lru[idx], newheader,
-                                                link);
-                       }
-               } else if (RESIGN(newheader)) {
-                       dns__qpzone_resigninsert(qpdb, idx, newheader);
-                       dns__qpzone_resigndelete(qpdb, rbtversion,
-                                                header DNS__DB_FLARG_PASS);
+               isc_heap_insert(qpdb->heaps[idx], newheader);
+               newheader->heap = qpdb->heaps[idx];
+               if (ZEROTTL(newheader)) {
+                       ISC_LIST_APPEND(qpdb->lru[idx], newheader, link);
+               } else {
+                       ISC_LIST_PREPEND(qpdb->lru[idx], newheader, link);
                }
 
                if (topheader != NULL) {
@@ -2858,8 +1730,6 @@ find_header:
                         * we INSIST on it.
                         */
                        INSIST(!loading);
-                       INSIST(rbtversion == NULL ||
-                              rbtversion->serial >= topheader->serial);
                        if (topheader_prev != NULL) {
                                topheader_prev->next = newheader;
                        } else {
@@ -2894,20 +1764,6 @@ find_header:
                }
        }
 
-       if (rbtversion != NULL && !newheader_nx) {
-               update_recordsandxfrsize(true, rbtversion, newheader,
-                                        nodename->length);
-       }
-
-       /*
-        * Check if the node now contains CNAME and other data.
-        */
-       if (rbtversion != NULL &&
-           cname_and_other_data(qpnode, rbtversion->serial))
-       {
-               return (DNS_R_CNAMEANDOTHER);
-       }
-
        if (addedrdataset != NULL) {
                dns__qpdb_bindrdataset(qpdb, qpnode, newheader, now,
                                       isc_rwlocktype_write,
@@ -2917,23 +1773,6 @@ find_header:
        return (ISC_R_SUCCESS);
 }
 
-static bool
-delegating_type(dns_qpdb_t *qpdb, dns_qpdata_t *node, dns_typepair_t type) {
-       if (IS_CACHE(qpdb)) {
-               if (type == dns_rdatatype_dname) {
-                       return (true);
-               } else {
-                       return (false);
-               }
-       } else if (type == dns_rdatatype_dname ||
-                  (type == dns_rdatatype_ns &&
-                   (node != qpdb->origin_node || IS_STUB(qpdb))))
-       {
-               return (true);
-       }
-       return (false);
-}
-
 static isc_result_t
 addnoqname(isc_mem_t *mctx, dns_slabheader_t *newheader,
           dns_rdataset_t *rdataset) {
@@ -3023,11 +1862,10 @@ dns__qpdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
                      dns_rdataset_t *addedrdataset DNS__DB_FLARG) {
        dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
        dns_qpdata_t *qpnode = (dns_qpdata_t *)node;
-       dns_qpdb_version_t *rbtversion = version;
        isc_region_t region;
        dns_slabheader_t *newheader = NULL;
        isc_result_t result;
-       bool delegating;
+       bool delegating = false;
        bool newnsec;
        isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
        isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
@@ -3036,33 +1874,10 @@ dns__qpdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
        dns_name_t *name = NULL;
 
        REQUIRE(VALID_QPDB(qpdb));
-       INSIST(rbtversion == NULL || rbtversion->qpdb == qpdb);
-
-       if (!IS_CACHE(qpdb)) {
-               /*
-                * SOA records are only allowed at top of zone.
-                */
-               if (rdataset->type == dns_rdatatype_soa &&
-                   node != qpdb->origin_node)
-               {
-                       return (DNS_R_NOTZONETOP);
-               }
-               TREE_RDLOCK(&qpdb->tree_lock, &tlocktype);
-               REQUIRE(((qpnode->nsec == DNS_DB_NSEC_NSEC3 &&
-                         (rdataset->type == dns_rdatatype_nsec3 ||
-                          rdataset->covers == dns_rdatatype_nsec3)) ||
-                        (qpnode->nsec != DNS_DB_NSEC_NSEC3 &&
-                         rdataset->type != dns_rdatatype_nsec3 &&
-                         rdataset->covers != dns_rdatatype_nsec3)));
-               TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
-       }
+       REQUIRE(version == NULL);
 
-       if (rbtversion == NULL) {
-               if (now == 0) {
-                       now = isc_stdtime_now();
-               }
-       } else {
-               now = 0;
+       if (now == 0) {
+               now = isc_stdtime_now();
        }
 
        result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
@@ -3072,7 +1887,7 @@ dns__qpdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
        }
 
        name = dns_fixedname_initname(&fixed);
-       dns__qpdb_nodefullname(db, node, name);
+       dns_name_copy(qpnode->name, name);
        dns_rdataset_getownercase(rdataset, name);
 
        newheader = (dns_slabheader_t *)region.base;
@@ -3090,64 +1905,41 @@ dns__qpdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
        }
        atomic_init(&newheader->count,
                    atomic_fetch_add_relaxed(&init_count, 1));
-       if (rbtversion != NULL) {
-               newheader->serial = rbtversion->serial;
-               now = 0;
-
-               if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
-                       DNS_SLABHEADER_SETATTR(newheader,
-                                              DNS_SLABHEADERATTR_RESIGN);
-                       newheader->resign =
-                               (isc_stdtime_t)(dns_time64_from32(
-                                                       rdataset->resign) >>
-                                               1);
-                       newheader->resign_lsb = rdataset->resign & 0x1;
-               }
-       } else {
-               newheader->serial = 1;
-               if ((rdataset->attributes & DNS_RDATASETATTR_PREFETCH) != 0) {
-                       DNS_SLABHEADER_SETATTR(newheader,
-                                              DNS_SLABHEADERATTR_PREFETCH);
-               }
-               if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
-                       DNS_SLABHEADER_SETATTR(newheader,
-                                              DNS_SLABHEADERATTR_NEGATIVE);
-               }
-               if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) {
-                       DNS_SLABHEADER_SETATTR(newheader,
-                                              DNS_SLABHEADERATTR_NXDOMAIN);
-               }
-               if ((rdataset->attributes & DNS_RDATASETATTR_OPTOUT) != 0) {
-                       DNS_SLABHEADER_SETATTR(newheader,
-                                              DNS_SLABHEADERATTR_OPTOUT);
-               }
-               if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
-                       result = addnoqname(qpdb->common.mctx, newheader,
-                                           rdataset);
-                       if (result != ISC_R_SUCCESS) {
-                               dns_slabheader_destroy(&newheader);
-                               return (result);
-                       }
+       newheader->serial = 1;
+       if ((rdataset->attributes & DNS_RDATASETATTR_PREFETCH) != 0) {
+               DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_PREFETCH);
+       }
+       if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
+               DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_NEGATIVE);
+       }
+       if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) {
+               DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_NXDOMAIN);
+       }
+       if ((rdataset->attributes & DNS_RDATASETATTR_OPTOUT) != 0) {
+               DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_OPTOUT);
+       }
+       if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
+               result = addnoqname(qpdb->common.mctx, newheader, rdataset);
+               if (result != ISC_R_SUCCESS) {
+                       dns_slabheader_destroy(&newheader);
+                       return (result);
                }
-               if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0) {
-                       result = addclosest(qpdb->common.mctx, newheader,
-                                           rdataset);
-                       if (result != ISC_R_SUCCESS) {
-                               dns_slabheader_destroy(&newheader);
-                               return (result);
-                       }
+       }
+       if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0) {
+               result = addclosest(qpdb->common.mctx, newheader, rdataset);
+               if (result != ISC_R_SUCCESS) {
+                       dns_slabheader_destroy(&newheader);
+                       return (result);
                }
        }
 
        /*
-        * If we're adding a delegation type (e.g. NS or DNAME for a zone,
-        * just DNAME for the cache), then we need to set the callback bit
-        * on the node.
+        * If we're adding a delegation type (which would be an NS or DNAME
+        * for a zone, but only DNAME counts for a cache), we need to set
+        * the callback bit on the node.
         */
-       if (delegating_type(qpdb, qpnode, rdataset->type)) {
+       if (rdataset->type == dns_rdatatype_dname) {
                delegating = true;
-       } else {
-               delegating = false;
        }
 
        /*
@@ -3170,7 +1962,7 @@ dns__qpdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
         * not necessarily have to be acquired but it will help purge
         * ancient entries more effectively.
         */
-       if (IS_CACHE(qpdb) && isc_mem_isovermem(qpdb->common.mctx)) {
+       if (isc_mem_isovermem(qpdb->common.mctx)) {
                cache_is_overmem = true;
        }
        if (delegating || newnsec || cache_is_overmem) {
@@ -3191,25 +1983,20 @@ dns__qpdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
                                  true);
        }
 
-       if (IS_CACHE(qpdb)) {
-               if (tlocktype == isc_rwlocktype_write) {
-                       cleanup_dead_nodes(qpdb,
-                                          qpnode->locknum DNS__DB_FLARG_PASS);
-               }
+       if (tlocktype == isc_rwlocktype_write) {
+               cleanup_dead_nodes(qpdb, qpnode->locknum DNS__DB_FLARG_PASS);
+       }
 
-               expire_ttl_headers(qpdb, qpnode->locknum, &tlocktype, now,
-                                  cache_is_overmem DNS__DB_FLARG_PASS);
+       expire_ttl_headers(qpdb, qpnode->locknum, &tlocktype, now,
+                          cache_is_overmem DNS__DB_FLARG_PASS);
 
-               /*
-                * If we've been holding a write lock on the tree just for
-                * cleaning, we can release it now.  However, we still need the
-                * node lock.
-                */
-               if (tlocktype == isc_rwlocktype_write && !delegating &&
-                   !newnsec)
-               {
-                       TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
-               }
+       /*
+        * If we've been holding a write lock on the tree just for
+        * cleaning, we can release it now.  However, we still need the
+        * node lock.
+        */
+       if (tlocktype == isc_rwlocktype_write && !delegating && !newnsec) {
+               TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
        }
 
        result = ISC_R_SUCCESS;
@@ -3232,8 +2019,8 @@ dns__qpdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
        }
 
        if (result == ISC_R_SUCCESS) {
-               result = dns__qpdb_add(qpdb, qpnode, name, rbtversion,
-                                      newheader, options, false, addedrdataset,
+               result = dns__qpdb_add(qpdb, qpnode, name, newheader, options,
+                                      false, addedrdataset,
                                       now DNS__DB_FLARG_PASS);
        }
        if (result == ISC_R_SUCCESS && delegating) {
@@ -3247,233 +2034,6 @@ dns__qpdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
        }
        INSIST(tlocktype == isc_rwlocktype_none);
 
-       /*
-        * Update the zone's secure status.  If version is non-NULL
-        * this is deferred until dns__qpdb_closeversion() is called.
-        */
-       if (result == ISC_R_SUCCESS && version == NULL && !IS_CACHE(qpdb)) {
-               dns__qpdb_setsecure(db, version, qpdb->origin_node);
-       }
-
-       return (result);
-}
-
-isc_result_t
-dns__qpdb_subtractrdataset(dns_db_t *db, dns_dbnode_t *node,
-                          dns_dbversion_t *version, dns_rdataset_t *rdataset,
-                          unsigned int options,
-                          dns_rdataset_t *newrdataset DNS__DB_FLARG) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       dns_qpdata_t *qpnode = (dns_qpdata_t *)node;
-       dns_qpdb_version_t *rbtversion = version;
-       dns_fixedname_t fname;
-       dns_name_t *nodename = dns_fixedname_initname(&fname);
-       dns_slabheader_t *topheader = NULL, *topheader_prev = NULL;
-       dns_slabheader_t *header = NULL, *newheader = NULL;
-       unsigned char *subresult = NULL;
-       isc_region_t region;
-       isc_result_t result;
-       qpdb_changed_t *changed = NULL;
-       isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
-       isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
-
-       REQUIRE(VALID_QPDB(qpdb));
-       REQUIRE(rbtversion != NULL && rbtversion->qpdb == qpdb);
-
-       if (!IS_CACHE(qpdb)) {
-               TREE_RDLOCK(&qpdb->tree_lock, &tlocktype);
-               REQUIRE(((qpnode->nsec == DNS_DB_NSEC_NSEC3 &&
-                         (rdataset->type == dns_rdatatype_nsec3 ||
-                          rdataset->covers == dns_rdatatype_nsec3)) ||
-                        (qpnode->nsec != DNS_DB_NSEC_NSEC3 &&
-                         rdataset->type != dns_rdatatype_nsec3 &&
-                         rdataset->covers != dns_rdatatype_nsec3)));
-               TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
-       }
-
-       dns__qpdb_nodefullname(db, node, nodename);
-
-       result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
-                                           &region, sizeof(dns_slabheader_t));
-       if (result != ISC_R_SUCCESS) {
-               return (result);
-       }
-
-       newheader = (dns_slabheader_t *)region.base;
-       dns_slabheader_reset(newheader, db, node);
-       dns__qpdb_setttl(newheader, rdataset->ttl);
-       newheader->type = DNS_TYPEPAIR_VALUE(rdataset->type, rdataset->covers);
-       atomic_init(&newheader->attributes, 0);
-       newheader->serial = rbtversion->serial;
-       newheader->trust = 0;
-       newheader->noqname = NULL;
-       newheader->closest = NULL;
-       atomic_init(&newheader->count,
-                   atomic_fetch_add_relaxed(&init_count, 1));
-       newheader->last_used = 0;
-       newheader->node = qpnode;
-       newheader->db = (dns_db_t *)qpdb;
-       if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
-               DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_RESIGN);
-               newheader->resign =
-                       (isc_stdtime_t)(dns_time64_from32(rdataset->resign) >>
-                                       1);
-               newheader->resign_lsb = rdataset->resign & 0x1;
-       } else {
-               newheader->resign = 0;
-               newheader->resign_lsb = 0;
-       }
-
-       NODE_WRLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
-
-       changed = add_changed(newheader, rbtversion DNS__DB_FLARG_PASS);
-       if (changed == NULL) {
-               dns_slabheader_destroy(&newheader);
-               NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock,
-                           &nlocktype);
-               return (ISC_R_NOMEMORY);
-       }
-
-       for (topheader = qpnode->data; topheader != NULL;
-            topheader = topheader->next)
-       {
-               if (topheader->type == newheader->type) {
-                       break;
-               }
-               topheader_prev = topheader;
-       }
-       /*
-        * If header isn't NULL, we've found the right type.  There may be
-        * IGNORE rdatasets between the top of the chain and the first real
-        * data.  We skip over them.
-        */
-       header = topheader;
-       while (header != NULL && IGNORE(header)) {
-               header = header->down;
-       }
-       if (header != NULL && EXISTS(header)) {
-               unsigned int flags = 0;
-               subresult = NULL;
-               result = ISC_R_SUCCESS;
-               if ((options & DNS_DBSUB_EXACT) != 0) {
-                       flags |= DNS_RDATASLAB_EXACT;
-                       if (newheader->ttl != header->ttl) {
-                               result = DNS_R_NOTEXACT;
-                       }
-               }
-               if (result == ISC_R_SUCCESS) {
-                       result = dns_rdataslab_subtract(
-                               (unsigned char *)header,
-                               (unsigned char *)newheader,
-                               (unsigned int)(sizeof(*newheader)),
-                               qpdb->common.mctx, qpdb->common.rdclass,
-                               (dns_rdatatype_t)header->type, flags,
-                               &subresult);
-               }
-               if (result == ISC_R_SUCCESS) {
-                       dns_slabheader_destroy(&newheader);
-                       newheader = (dns_slabheader_t *)subresult;
-                       dns_slabheader_reset(newheader, db, node);
-                       dns_slabheader_copycase(newheader, header);
-                       if (RESIGN(header)) {
-                               DNS_SLABHEADER_SETATTR(
-                                       newheader, DNS_SLABHEADERATTR_RESIGN);
-                               newheader->resign = header->resign;
-                               newheader->resign_lsb = header->resign_lsb;
-                               dns__qpzone_resigninsert(qpdb, qpnode->locknum,
-                                                        newheader);
-                       }
-                       /*
-                        * We have to set the serial since the rdataslab
-                        * subtraction routine copies the reserved portion of
-                        * header, not newheader.
-                        */
-                       newheader->serial = rbtversion->serial;
-                       /*
-                        * XXXJT: dns_rdataslab_subtract() copied the pointers
-                        * to additional info.  We need to clear these fields
-                        * to avoid having duplicated references.
-                        */
-                       update_recordsandxfrsize(true, rbtversion, newheader,
-                                                nodename->length);
-               } else if (result == DNS_R_NXRRSET) {
-                       /*
-                        * This subtraction would remove all of the rdata;
-                        * add a nonexistent header instead.
-                        */
-                       dns_slabheader_destroy(&newheader);
-                       newheader = dns_slabheader_new((dns_db_t *)qpdb,
-                                                      (dns_dbnode_t *)qpnode);
-                       dns__qpdb_setttl(newheader, 0);
-                       newheader->type = topheader->type;
-                       atomic_init(&newheader->attributes,
-                                   DNS_SLABHEADERATTR_NONEXISTENT);
-                       newheader->serial = rbtversion->serial;
-               } else {
-                       dns_slabheader_destroy(&newheader);
-                       goto unlock;
-               }
-
-               /*
-                * If we're here, we want to link newheader in front of
-                * topheader.
-                */
-               INSIST(rbtversion->serial >= topheader->serial);
-               update_recordsandxfrsize(false, rbtversion, header,
-                                        nodename->length);
-               if (topheader_prev != NULL) {
-                       topheader_prev->next = newheader;
-               } else {
-                       qpnode->data = newheader;
-               }
-               newheader->next = topheader->next;
-               newheader->down = topheader;
-               topheader->next = newheader;
-               qpnode->dirty = 1;
-               changed->dirty = true;
-               dns__qpzone_resigndelete(qpdb, rbtversion,
-                                        header DNS__DB_FLARG_PASS);
-       } else {
-               /*
-                * The rdataset doesn't exist, so we don't need to do anything
-                * to satisfy the deletion request.
-                */
-               dns_slabheader_destroy(&newheader);
-               if ((options & DNS_DBSUB_EXACT) != 0) {
-                       result = DNS_R_NOTEXACT;
-               } else {
-                       result = DNS_R_UNCHANGED;
-               }
-       }
-
-       if (result == ISC_R_SUCCESS && newrdataset != NULL) {
-               dns__qpdb_bindrdataset(qpdb, qpnode, newheader, 0,
-                                      isc_rwlocktype_write,
-                                      newrdataset DNS__DB_FLARG_PASS);
-       }
-
-       if (result == DNS_R_NXRRSET && newrdataset != NULL &&
-           (options & DNS_DBSUB_WANTOLD) != 0)
-       {
-               dns__qpdb_bindrdataset(qpdb, qpnode, header, 0,
-                                      isc_rwlocktype_write,
-                                      newrdataset DNS__DB_FLARG_PASS);
-       }
-
-unlock:
-       NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
-
-       /*
-        * Update the zone's secure status.  If version is non-NULL
-        * this is deferred until dns__qpdb_closeversion() is called.
-        */
-       if (result == ISC_R_SUCCESS && version == NULL && !IS_CACHE(qpdb)) {
-               RWLOCK(&qpdb->lock, isc_rwlocktype_read);
-               version = qpdb->current_version;
-               RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
-               dns__qpdb_setsecure(db, version, qpdb->origin_node);
-       }
-
        return (result);
 }
 
@@ -3483,15 +2043,12 @@ dns__qpdb_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
                         dns_rdatatype_t covers DNS__DB_FLARG) {
        dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
        dns_qpdata_t *qpnode = (dns_qpdata_t *)node;
-       dns_qpdb_version_t *rbtversion = version;
-       dns_fixedname_t fname;
-       dns_name_t *nodename = dns_fixedname_initname(&fname);
        isc_result_t result;
        dns_slabheader_t *newheader = NULL;
        isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
 
        REQUIRE(VALID_QPDB(qpdb));
-       INSIST(rbtversion == NULL || rbtversion->qpdb == qpdb);
+       REQUIRE(version == NULL);
 
        if (type == dns_rdatatype_any) {
                return (ISC_R_NOTIMPLEMENTED);
@@ -3504,29 +2061,12 @@ dns__qpdb_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
        newheader->type = DNS_TYPEPAIR_VALUE(type, covers);
        dns__qpdb_setttl(newheader, 0);
        atomic_init(&newheader->attributes, DNS_SLABHEADERATTR_NONEXISTENT);
-       if (rbtversion != NULL) {
-               newheader->serial = rbtversion->serial;
-       }
-
-       dns__qpdb_nodefullname(db, node, nodename);
 
        NODE_WRLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
-       result = dns__qpdb_add(qpdb, qpnode, nodename, rbtversion, newheader,
-                              DNS_DBADD_FORCE, false, NULL,
-                              0 DNS__DB_FLARG_PASS);
+       result = dns__qpdb_add(qpdb, qpnode, NULL, newheader, DNS_DBADD_FORCE,
+                              false, NULL, 0 DNS__DB_FLARG_PASS);
        NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
 
-       /*
-        * Update the zone's secure status.  If version is non-NULL
-        * this is deferred until dns__qpdb_closeversion() is called.
-        */
-       if (result == ISC_R_SUCCESS && version == NULL && !IS_CACHE(qpdb)) {
-               RWLOCK(&qpdb->lock, isc_rwlocktype_read);
-               version = qpdb->current_version;
-               RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
-               dns__qpdb_setsecure(db, version, qpdb->origin_node);
-       }
-
        return (result);
 }
 
@@ -3589,7 +2129,6 @@ dns__qpdb_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) {
                                 isc_rwlocktype_none DNS__DB_FLARG_PASS);
                *nodep = qpdb->origin_node;
        } else {
-               INSIST(IS_CACHE(qpdb));
                result = ISC_R_NOTFOUND;
        }
 
@@ -3612,31 +2151,17 @@ dns__qpdb_unlocknode(dns_db_t *db, dns_dbnode_t *node, isc_rwlocktype_t type) {
        RWUNLOCK(&qpdb->node_locks[qpnode->locknum].lock, type);
 }
 
-isc_result_t
-dns__qpdb_nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name) {
-       dns_qpdb_t *qpdb = (dns_qpdb_t *)db;
-       dns_qpdata_t *qpnode = (dns_qpdata_t *)node;
-       isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
-
-       REQUIRE(VALID_QPDB(qpdb));
-       REQUIRE(node != NULL);
-       REQUIRE(name != NULL);
-
-       TREE_RDLOCK(&qpdb->tree_lock, &tlocktype);
-       dns_name_copy(qpnode->name, name);
-       TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
-
-       return (ISC_R_SUCCESS);
-}
-
 isc_result_t
 dns__qpdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
                 dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
                 void *driverarg ISC_ATTR_UNUSED, dns_db_t **dbp) {
        dns_qpdb_t *qpdb = NULL;
        isc_result_t result;
-       int i;
        isc_mem_t *hmctx = mctx;
+       int i;
+
+       /* This database implementation only supports cache semantics */
+       REQUIRE(type == dns_dbtype_cache);
 
        qpdb = isc_mem_get(mctx, sizeof(*qpdb));
        *qpdb = (dns_qpdb_t){
@@ -3645,7 +2170,6 @@ dns__qpdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
                .current_serial = 1,
                .least_serial = 1,
                .next_serial = 2,
-               .open_versions = ISC_LIST_INITIALIZER,
        };
 
        isc_refcount_init(&qpdb->common.references, 1);
@@ -3657,15 +2181,8 @@ dns__qpdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
                hmctx = (isc_mem_t *)argv[0];
        }
 
-       if (type == dns_dbtype_cache) {
-               qpdb->common.methods = &dns__qpdb_cachemethods;
-               qpdb->common.attributes |= DNS_DBATTR_CACHE;
-       } else if (type == dns_dbtype_stub) {
-               qpdb->common.methods = &dns__qpdb_zonemethods;
-               qpdb->common.attributes |= DNS_DBATTR_STUB;
-       } else {
-               qpdb->common.methods = &dns__qpdb_zonemethods;
-       }
+       qpdb->common.methods = &dns__qpdb_cachemethods;
+       qpdb->common.attributes |= DNS_DBATTR_CACHE;
 
        isc_rwlock_init(&qpdb->lock);
        TREE_INITLOCK(&qpdb->tree_lock);
@@ -3677,14 +2194,7 @@ dns__qpdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
         * as commented with the definition of DEFAULT_CACHE_NODE_LOCK_COUNT.
         */
        if (qpdb->node_lock_count == 0) {
-               if (IS_CACHE(qpdb)) {
-                       qpdb->node_lock_count = DEFAULT_CACHE_NODE_LOCK_COUNT;
-               } else {
-                       qpdb->node_lock_count = DEFAULT_NODE_LOCK_COUNT;
-               }
-       } else if (qpdb->node_lock_count < 2 && IS_CACHE(qpdb)) {
-               result = ISC_R_RANGE;
-               goto cleanup_tree_lock;
+               qpdb->node_lock_count = DEFAULT_CACHE_NODE_LOCK_COUNT;
        }
        INSIST(qpdb->node_lock_count < (1 << DNS_RBT_LOCKLENGTH));
        qpdb->node_locks = isc_mem_cget(mctx, qpdb->node_lock_count,
@@ -3692,13 +2202,11 @@ dns__qpdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
 
        qpdb->common.update_listeners = cds_lfht_new(16, 16, 0, 0, NULL);
 
-       if (IS_CACHE(qpdb)) {
-               dns_rdatasetstats_create(mctx, &qpdb->rrsetstats);
-               qpdb->lru = isc_mem_cget(mctx, qpdb->node_lock_count,
-                                        sizeof(dns_slabheaderlist_t));
-               for (i = 0; i < (int)qpdb->node_lock_count; i++) {
-                       ISC_LIST_INIT(qpdb->lru[i]);
-               }
+       dns_rdatasetstats_create(mctx, &qpdb->rrsetstats);
+       qpdb->lru = isc_mem_cget(mctx, qpdb->node_lock_count,
+                                sizeof(dns_slabheaderlist_t));
+       for (i = 0; i < (int)qpdb->node_lock_count; i++) {
+               ISC_LIST_INIT(qpdb->lru[i]);
        }
 
        /*
@@ -3710,9 +2218,8 @@ dns__qpdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
                qpdb->heaps[i] = NULL;
        }
 
-       qpdb->sooner = IS_CACHE(qpdb) ? ttl_sooner : resign_sooner;
        for (i = 0; i < (int)qpdb->node_lock_count; i++) {
-               isc_heap_create(hmctx, qpdb->sooner, set_index, 0,
+               isc_heap_create(hmctx, ttl_sooner, set_index, 0,
                                &qpdb->heaps[i]);
        }
 
@@ -3757,65 +2264,12 @@ dns__qpdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
        dns_qp_create(mctx, &qpmethods, qpdb, &qpdb->nsec);
        dns_qp_create(mctx, &qpmethods, qpdb, &qpdb->nsec3);
 
-       /*
-        * In order to set the node callback bit correctly in zone databases,
-        * we need to know if the node has the origin name of the zone.
-        * In loading_addrdataset() we could simply compare the new name
-        * to the origin name, but this is expensive.  Also, we don't know the
-        * node name in dns__qpdb_addrdataset(), so we need another way of
-        * knowing the zone's top.
-        *
-        * We now explicitly create a node for the zone's origin, and then
-        * we simply remember the node's address.  This is safe, because
-        * the top-of-zone node can never be deleted, nor can its address
-        * change.
-        */
-       if (!IS_CACHE(qpdb)) {
-               qpdb->origin_node = dns_qpdata_create(qpdb,
-                                                     &qpdb->common.origin);
-               result = dns_qp_insert(qpdb->tree, qpdb->origin_node, 0);
-               INSIST(result == ISC_R_SUCCESS);
-               INSIST(qpdb->origin_node != NULL);
-               qpdb->origin_node->nsec = DNS_DB_NSEC_NORMAL;
-
-               /*
-                * Add an apex node to the NSEC3 tree so that NSEC3 searches
-                * return partial matches when there is only a single NSEC3
-                * record in the tree.
-                */
-               qpdb->nsec3_origin_node =
-                       dns_qpdata_create(qpdb, &qpdb->common.origin);
-               result = dns_qp_insert(qpdb->nsec3, qpdb->nsec3_origin_node, 0);
-               INSIST(result == ISC_R_SUCCESS);
-               INSIST(qpdb->nsec3_origin_node != NULL);
-               qpdb->nsec3_origin_node->nsec = DNS_DB_NSEC_NSEC3;
-       }
-
-       /*
-        * Version Initialization.
-        */
-       qpdb->current_version = allocate_version(mctx, 1, 1, false);
-       qpdb->current_version->qpdb = qpdb;
-       isc_rwlock_init(&qpdb->current_version->rwlock);
-
-       /*
-        * Keep the current version in the open list so that list operation
-        * won't happen in normal lookup operations.
-        */
-       PREPEND(qpdb->open_versions, qpdb->current_version, link);
-
        qpdb->common.magic = DNS_DB_MAGIC;
        qpdb->common.impmagic = QPDB_MAGIC;
 
        *dbp = (dns_db_t *)qpdb;
 
        return (ISC_R_SUCCESS);
-
-cleanup_tree_lock:
-       TREE_DESTROYLOCK(&qpdb->tree_lock);
-       isc_rwlock_destroy(&qpdb->lock);
-       isc_mem_put(mctx, qpdb, sizeof(*qpdb));
-       return (result);
 }
 
 /*
@@ -3828,11 +2282,6 @@ rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) {
 
        rbtiterator = (qpdb_rdatasetiter_t *)(*iteratorp);
 
-       if (rbtiterator->common.version != NULL) {
-               dns__qpdb_closeversion(rbtiterator->common.db,
-                                      &rbtiterator->common.version,
-                                      false DNS__DB_FLARG_PASS);
-       }
        dns__db_detachnode(rbtiterator->common.db,
                           &rbtiterator->common.node DNS__DB_FLARG_PASS);
        isc_mem_put(rbtiterator->common.db->mctx, rbtiterator,
@@ -3854,9 +2303,9 @@ iterator_active(dns_qpdb_t *qpdb, qpdb_rdatasetiter_t *rbtiterator,
        }
 
        /*
-        * If this is a zone or this header still active then return it.
+        * If this header is still active then return it.
         */
-       if (!IS_CACHE(qpdb) || ACTIVE(header, rbtiterator->common.now)) {
+       if (ACTIVE(header, rbtiterator->common.now)) {
                return (true);
        }
 
@@ -3875,9 +2324,7 @@ rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
        qpdb_rdatasetiter_t *rbtiterator = (qpdb_rdatasetiter_t *)iterator;
        dns_qpdb_t *qpdb = (dns_qpdb_t *)(rbtiterator->common.db);
        dns_qpdata_t *qpnode = rbtiterator->common.node;
-       dns_qpdb_version_t *rbtversion = rbtiterator->common.version;
        dns_slabheader_t *header = NULL, *top_next = NULL;
-       uint32_t serial = IS_CACHE(qpdb) ? 1 : rbtversion->serial;
        isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
 
        NODE_RDLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
@@ -3890,8 +2337,7 @@ rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
                                        break;
                                }
                                header = header->down;
-                       } else if (header->serial <= serial && !IGNORE(header))
-                       {
+                       } else if (header->serial <= 1 && !IGNORE(header)) {
                                if (!iterator_active(qpdb, rbtiterator, header))
                                {
                                        header = NULL;
@@ -3922,9 +2368,7 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
        qpdb_rdatasetiter_t *rbtiterator = (qpdb_rdatasetiter_t *)iterator;
        dns_qpdb_t *qpdb = (dns_qpdb_t *)(rbtiterator->common.db);
        dns_qpdata_t *qpnode = rbtiterator->common.node;
-       dns_qpdb_version_t *rbtversion = rbtiterator->common.version;
        dns_slabheader_t *header = NULL, *top_next = NULL;
-       uint32_t serial = IS_CACHE(qpdb) ? 1 : rbtversion->serial;
        dns_typepair_t type, negtype;
        dns_rdatatype_t rdtype, covers;
        isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
@@ -3973,8 +2417,7 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
                                        break;
                                }
                                header = header->down;
-                       } else if (header->serial <= serial && !IGNORE(header))
-                       {
+                       } else if (header->serial <= 1 && !IGNORE(header)) {
                                if (!iterator_active(qpdb, rbtiterator, header))
                                {
                                        header = NULL;
@@ -4552,64 +2995,6 @@ dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
        return (ISC_R_SUCCESS);
 }
 
-void
-dns__qpdb_freeglue(dns_glue_t *glue_list) {
-       if (glue_list == (void *)-1) {
-               return;
-       }
-
-       dns_glue_t *glue = glue_list;
-       while (glue != NULL) {
-               dns_glue_t *next = glue->next;
-
-               if (dns_rdataset_isassociated(&glue->rdataset_a)) {
-                       dns_rdataset_disassociate(&glue->rdataset_a);
-               }
-               if (dns_rdataset_isassociated(&glue->sigrdataset_a)) {
-                       dns_rdataset_disassociate(&glue->sigrdataset_a);
-               }
-
-               if (dns_rdataset_isassociated(&glue->rdataset_aaaa)) {
-                       dns_rdataset_disassociate(&glue->rdataset_aaaa);
-               }
-               if (dns_rdataset_isassociated(&glue->sigrdataset_aaaa)) {
-                       dns_rdataset_disassociate(&glue->sigrdataset_aaaa);
-               }
-
-               dns_rdataset_invalidate(&glue->rdataset_a);
-               dns_rdataset_invalidate(&glue->sigrdataset_a);
-               dns_rdataset_invalidate(&glue->rdataset_aaaa);
-               dns_rdataset_invalidate(&glue->sigrdataset_aaaa);
-
-               isc_mem_putanddetach(&glue->mctx, glue, sizeof(*glue));
-
-               glue = next;
-       }
-}
-
-static void
-free_gluelist_rcu(struct rcu_head *rcu_head) {
-       dns_glue_t *glue = caa_container_of(rcu_head, dns_glue_t, rcu_head);
-
-       dns__qpdb_freeglue(glue);
-}
-
-static void
-free_gluetable(struct cds_wfs_stack *glue_stack) {
-       struct cds_wfs_head *head = __cds_wfs_pop_all(glue_stack);
-       struct cds_wfs_node *node = NULL, *next = NULL;
-
-       rcu_read_lock();
-       cds_wfs_for_each_blocking_safe(head, node, next) {
-               dns_slabheader_t *header =
-                       caa_container_of(node, dns_slabheader_t, wfs_node);
-               dns_glue_t *glue = rcu_xchg_pointer(&header->glue_list, NULL);
-
-               call_rcu(&glue->rcu_head, free_gluelist_rcu);
-       }
-       rcu_read_unlock();
-}
-
 void
 dns__qpdb_deletedata(dns_db_t *db ISC_ATTR_UNUSED,
                     dns_dbnode_t *node ISC_ATTR_UNUSED, void *data) {
@@ -4620,27 +3005,19 @@ dns__qpdb_deletedata(dns_db_t *db ISC_ATTR_UNUSED,
                isc_heap_delete(header->heap, header->heap_index);
        }
 
-       if (IS_CACHE(qpdb)) {
-               update_rrsetstats(qpdb->rrsetstats, header->type,
-                                 atomic_load_acquire(&header->attributes),
-                                 false);
+       update_rrsetstats(qpdb->rrsetstats, header->type,
+                         atomic_load_acquire(&header->attributes), false);
 
-               if (ISC_LINK_LINKED(header, link)) {
-                       int idx = QPDB_HEADERNODE(header)->locknum;
-                       INSIST(IS_CACHE(qpdb));
-                       ISC_LIST_UNLINK(qpdb->lru[idx], header, link);
-               }
+       if (ISC_LINK_LINKED(header, link)) {
+               int idx = QPDB_HEADERNODE(header)->locknum;
+               ISC_LIST_UNLINK(qpdb->lru[idx], header, link);
+       }
 
-               if (header->noqname != NULL) {
-                       dns_slabheader_freeproof(db->mctx, &header->noqname);
-               }
-               if (header->closest != NULL) {
-                       dns_slabheader_freeproof(db->mctx, &header->closest);
-               }
-       } else {
-               if (header->glue_list) {
-                       dns__qpdb_freeglue(header->glue_list);
-               }
+       if (header->noqname != NULL) {
+               dns_slabheader_freeproof(db->mctx, &header->noqname);
+       }
+       if (header->closest != NULL) {
+               dns_slabheader_freeproof(db->mctx, &header->closest);
        }
 }
 
index 23c38243e10a4ed831a572306b04871cf1c322e7..e6190484237dbd44515d166c92f27a4d6e4d5c40 100644 (file)
@@ -74,14 +74,8 @@ struct dns_qpdata {
         * after acquiring the tree lock.
         */
        unsigned int               : 0; /* start of bitfields c/o tree lock */
-       unsigned int is_root       : 1; /*%< range is 0..1 */
-       unsigned int color         : 1; /*%< range is 0..1 */
        unsigned int find_callback : 1; /*%< range is 0..1 */
-       bool absolute              : 1; /*%< node with absolute DNS name */
        unsigned int nsec          : 2; /*%< range is 0..3 */
-       unsigned int namelen       : 8; /*%< range is 1..255 */
-       unsigned int offsetlen     : 8; /*%< range is 1..128 */
-       unsigned int oldnamelen    : 8; /*%< range is 1..255 */
        unsigned int               : 0; /* end of bitfields c/o tree lock */
        /*@}*/
 
@@ -103,7 +97,7 @@ struct dns_qpdata {
 
        /*@{*/
        /*!
-        * These values are used in the RBT DB implementation.  The appropriate
+        * These values are used in the QPDB implementation.  The appropriate
         * node lock must be held before accessing them.
         *
         * Note: The two "unsigned int :0;" unnamed bitfields on either
@@ -122,7 +116,6 @@ struct dns_qpdata {
        void *data;
        uint8_t       : 0; /* start of bitfields c/o node lock */
        uint8_t dirty : 1;
-       uint8_t wild  : 1;
        uint8_t       : 0; /* end of bitfields c/o node lock */
        uint16_t locknum;  /* note that this is not in the bitfield */
        isc_refcount_t references;
@@ -138,43 +131,6 @@ typedef struct qpdb_changed {
 
 typedef ISC_LIST(qpdb_changed_t) qpdb_changedlist_t;
 
-struct dns_qpdb_version {
-       /* Not locked */
-       uint32_t serial;
-       dns_qpdb_t *qpdb;
-       /*
-        * Protected in the refcount routines.
-        * XXXJT: should we change the lock policy based on the refcount
-        * performance?
-        */
-       isc_refcount_t references;
-       /* Locked by database lock. */
-       bool writer;
-       bool commit_ok;
-       qpdb_changedlist_t changed_list;
-       dns_slabheaderlist_t resigned_list;
-       ISC_LINK(dns_qpdb_version_t) link;
-       bool secure;
-       bool havensec3;
-       /* NSEC3 parameters */
-       dns_hash_t hash;
-       uint8_t flags;
-       uint16_t iterations;
-       uint8_t salt_length;
-       unsigned char salt[DNS_NSEC3_SALTSIZE];
-
-       /*
-        * records and xfrsize are covered by rwlock.
-        */
-       isc_rwlock_t rwlock;
-       uint64_t records;
-       uint64_t xfrsize;
-
-       struct cds_wfs_stack glue_stack;
-};
-
-typedef ISC_LIST(dns_qpdb_version_t) qpdb_versionlist_t;
-
 struct dns_qpdb {
        /* Unlocked. */
        dns_db_t common;
@@ -196,9 +152,6 @@ struct dns_qpdb {
        uint32_t current_serial;
        uint32_t least_serial;
        uint32_t next_serial;
-       dns_qpdb_version_t *current_version;
-       dns_qpdb_version_t *future_version;
-       qpdb_versionlist_t open_versions;
        isc_loop_t *loop;
        dns_dbnode_t *soanode;
        dns_dbnode_t *nsnode;
@@ -242,7 +195,6 @@ struct dns_qpdb {
         */
        isc_mem_t *hmctx;
        isc_heap_t **heaps;
-       isc_heapcompare_t sooner;
 
        /* Locked by tree_lock. */
        dns_qp_t *tree;
@@ -258,7 +210,6 @@ struct dns_qpdb {
  */
 typedef struct {
        dns_qpdb_t *qpdb;
-       dns_qpdb_version_t *rbtversion;
        uint32_t serial;
        unsigned int options;
        dns_qpchain_t chain;
@@ -448,9 +399,6 @@ dns__qpdb_bindrdataset(dns_qpdb_t *qpdb, dns_qpdata_t *node,
 isc_result_t
 dns__qpdb_nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name);
 
-void
-dns__qpdb_freeglue(dns_glue_t *glue_list);
-
 void
 dns__qpdb_newref(dns_qpdb_t *qpdb, dns_qpdata_t *node,
                 isc_rwlocktype_t locktype DNS__DB_FLARG);
@@ -477,23 +425,14 @@ dns__qpdb_decref(dns_qpdb_t *qpdb, dns_qpdata_t *node, uint32_t least_serial,
 
 isc_result_t
 dns__qpdb_add(dns_qpdb_t *qpdb, dns_qpdata_t *qpnode,
-             const dns_name_t *nodename, dns_qpdb_version_t *rbtversion,
-             dns_slabheader_t *newheader, unsigned int options, bool loading,
-             dns_rdataset_t *addedrdataset, isc_stdtime_t now DNS__DB_FLARG);
+             const dns_name_t *nodename, dns_slabheader_t *newheader,
+             unsigned int options, bool loading, dns_rdataset_t *addedrdataset,
+             isc_stdtime_t now DNS__DB_FLARG);
 /*%<
  * Add a slab header 'newheader' to a node in an RBT database.
  * The caller must have the node write-locked.
  */
 
-void
-dns__qpdb_setsecure(dns_db_t *db, dns_qpdb_version_t *version,
-                   dns_dbnode_t *origin);
-/*%<
- * Update the secure status for an RBT database version 'version'.
- * The version will be marked secure if it is fully signed and
- * and contains a complete NSEC/NSEC3 chain.
- */
-
 void
 dns__qpdb_mark(dns_slabheader_t *header, uint_least16_t flag);
 /*%<
@@ -509,43 +448,6 @@ dns__qpdb_setttl(dns_slabheader_t *header, dns_ttl_t newttl);
  * also update the TTL heap accordingly.
  */
 
-/*
- * Functions specific to zone databases that are also called from qpdb.c.
- */
-void
-dns__qpzone_resigninsert(dns_qpdb_t *qpdb, int idx,
-                        dns_slabheader_t *newheader);
-void
-dns__qpzone_resigndelete(dns_qpdb_t *qpdb, dns_qpdb_version_t *version,
-                        dns_slabheader_t *header DNS__DB_FLARG);
-/*%<
- * Insert/delete a node from the zone database's resigning heap.
- */
-
-isc_result_t
-dns__qpzone_wildcardmagic(dns_qpdb_t *qpdb, const dns_name_t *name, bool lock);
-/*%<
- * Add the necessary magic for the wildcard name 'name'
- * to be found in 'qpdb'.
- *
- * In order for wildcard matching to work correctly in
- * zone_find(), we must ensure that a node for the wildcarding
- * level exists in the database, and has its 'find_callback'
- * and 'wild' bits set.
- *
- * E.g. if the wildcard name is "*.sub.example." then we
- * must ensure that "sub.example." exists and is marked as
- * a wildcard level.
- *
- * The tree must be write-locked.
- */
-isc_result_t
-dns__qpzone_addwildcards(dns_qpdb_t *qpdb, const dns_name_t *name, bool lock);
-/*%<
- * If 'name' is or contains a wildcard name, create a node for it in the
- * database. The tree must be write-locked.
- */
-
 /*
  * Cache-specific functions that are called from qpdb.c
  */
index 9002f95a1cc91b1ce3346352738db07c222ef3cf..e7a6a296b017041d558bd711add2cb91c67311ed 100644 (file)
 #undef CHECK
 #include <tests/dns.h>
 
-const char *ownercase_vectors[12][2] = {
-       {
-               "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz",
-               "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz",
-       },
-       {
-               "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz",
-               "AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ",
-       },
-       {
-               "AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ",
-               "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz",
-       },
-       {
-               "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ",
-               "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz",
-       },
-       {
-               "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVxXyYzZ",
-               "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvxxyyzz",
-       },
-       {
-               "WwW.ExAmPlE.OrG",
-               "wWw.eXaMpLe.oRg",
-       },
-       {
-               "_SIP.tcp.example.org",
-               "_sip.TCP.example.org",
-       },
-       {
-               "bind-USERS.lists.example.org",
-               "bind-users.lists.example.org",
-       },
-       {
-               "a0123456789.example.org",
-               "A0123456789.example.org",
-       },
-       {
-               "\\000.example.org",
-               "\\000.example.org",
-       },
-       {
-               "wWw.\\000.isc.org",
-               "www.\\000.isc.org",
-       },
-       {
-               "\255.example.org",
-               "\255.example.ORG",
-       }
-};
-
-static bool
-ownercase_test_one(const char *str1, const char *str2) {
-       isc_result_t result;
-       db_nodelock_t node_locks[1];
-       dns_qpdb_t qpdb = {
-               .common.methods = &dns__qpdb_zonemethods,
-               .common.mctx = mctx,
-               .node_locks = node_locks,
-       };
-       dns_qpdata_t rbtnode = { .locknum = 0 };
-       dns_slabheader_t header = {
-               .node = &rbtnode,
-               .db = (dns_db_t *)&qpdb,
-       };
-       unsigned char *raw = (unsigned char *)(&header) + sizeof(header);
-       dns_rdataset_t rdataset = {
-               .magic = DNS_RDATASET_MAGIC,
-               .slab = { .db = (dns_db_t *)&qpdb,
-                         .node = &rbtnode,
-                         .raw = raw },
-               .methods = &dns_rdataslab_rdatasetmethods,
-       };
-       isc_buffer_t b;
-       dns_fixedname_t fname1, fname2;
-       dns_name_t *name1 = dns_fixedname_initname(&fname1);
-       dns_name_t *name2 = dns_fixedname_initname(&fname2);
-
-       memset(node_locks, 0, sizeof(node_locks));
-       /* Minimal initialization of the mock objects */
-       NODE_INITLOCK(&qpdb.node_locks[0].lock);
-
-       isc_buffer_constinit(&b, str1, strlen(str1));
-       isc_buffer_add(&b, strlen(str1));
-       result = dns_name_fromtext(name1, &b, dns_rootname, 0, NULL);
-       assert_int_equal(result, ISC_R_SUCCESS);
-
-       isc_buffer_constinit(&b, str2, strlen(str2));
-       isc_buffer_add(&b, strlen(str2));
-       result = dns_name_fromtext(name2, &b, dns_rootname, 0, NULL);
-       assert_int_equal(result, ISC_R_SUCCESS);
-
-       /* Store the case from name1 */
-       dns_rdataset_setownercase(&rdataset, name1);
-
-       assert_true(CASESET(&header));
-
-       /* Retrieve the case to name2 */
-       dns_rdataset_getownercase(&rdataset, name2);
-
-       NODE_DESTROYLOCK(&qpdb.node_locks[0].lock);
-
-       return (dns_name_caseequal(name1, name2));
-}
-
-ISC_RUN_TEST_IMPL(ownercase) {
-       UNUSED(state);
-
-       for (size_t n = 0; n < ARRAY_SIZE(ownercase_vectors); n++) {
-               assert_true(ownercase_test_one(ownercase_vectors[n][0],
-                                              ownercase_vectors[n][1]));
-       }
-
-       assert_false(ownercase_test_one("W.example.org", "\\000.example.org"));
-
-       /* Ö and ö in ISO Latin 1 */
-       assert_false(ownercase_test_one("\\216", "\\246"));
-}
-
-ISC_RUN_TEST_IMPL(setownercase) {
-       isc_result_t result;
-       db_nodelock_t node_locks[1];
-       dns_qpdb_t qpdb = {
-               .common.methods = &dns__qpdb_zonemethods,
-               .common.mctx = mctx,
-               .node_locks = node_locks,
-       };
-       dns_qpdata_t rbtnode = { .locknum = 0 };
-       dns_slabheader_t header = {
-               .node = &rbtnode,
-               .db = (dns_db_t *)&qpdb,
-       };
-       unsigned char *raw = (unsigned char *)(&header) + sizeof(header);
-       dns_rdataset_t rdataset = {
-               .magic = DNS_RDATASET_MAGIC,
-               .slab = { .db = (dns_db_t *)&qpdb,
-                         .node = &rbtnode,
-                         .raw = raw },
-               .methods = &dns_rdataslab_rdatasetmethods,
-       };
-       const char *str1 =
-               "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
-       isc_buffer_t b;
-       dns_fixedname_t fname1, fname2;
-       dns_name_t *name1 = dns_fixedname_initname(&fname1);
-       dns_name_t *name2 = dns_fixedname_initname(&fname2);
-
-       UNUSED(state);
-
-       /* Minimal initialization of the mock objects */
-       memset(node_locks, 0, sizeof(node_locks));
-       NODE_INITLOCK(&qpdb.node_locks[0].lock);
-
-       isc_buffer_constinit(&b, str1, strlen(str1));
-       isc_buffer_add(&b, strlen(str1));
-       result = dns_name_fromtext(name1, &b, dns_rootname, 0, NULL);
-       assert_int_equal(result, ISC_R_SUCCESS);
-
-       isc_buffer_constinit(&b, str1, strlen(str1));
-       isc_buffer_add(&b, strlen(str1));
-       result = dns_name_fromtext(name2, &b, dns_rootname, 0, NULL);
-       assert_int_equal(result, ISC_R_SUCCESS);
-
-       assert_false(CASESET(&header));
-
-       /* Retrieve the case to name2 */
-       dns_rdataset_getownercase(&rdataset, name2);
-
-       NODE_DESTROYLOCK(&qpdb.node_locks[0].lock);
-
-       assert_true(dns_name_caseequal(name1, name2));
-}
-
 /*
  * Add to a cache DB 'db' an rdataset of type 'rtype' at a name
  * <idx>.example.com. The rdataset would contain one data, and rdata_len is
@@ -372,8 +199,6 @@ ISC_RUN_TEST_IMPL(overmempurge_longname) {
 }
 
 ISC_TEST_LIST_START
-ISC_TEST_ENTRY(ownercase)
-ISC_TEST_ENTRY(setownercase)
 ISC_TEST_ENTRY(overmempurge_bigrdata)
 ISC_TEST_ENTRY(overmempurge_longname)
 ISC_TEST_LIST_END