/* Locked by tree_lock. */
dns_qp_t *tree;
- dns_qp_t *nsec;
isc_mem_t *hmctx; /* Memory context for the heaps */
};
/*
- * Note that the QP cache database only needs a single QP iterator, because
- * unlike the QP zone database, NSEC3 records are cached in the main tree.
- *
- * If we ever implement synth-from-dnssec using NSEC3 records, we'll need
- * to have a separate tree for NSEC3 records, and to copy in the more complex
- * iterator implementation from qpzone.c.
+ * In the cache, NSEC3 records are currently stored in the NORMAL
+ * namespace. If we ever implement synth-from-dnssec using NSEC3 records,
+ * they'll need be moved into the NSEC3 namespace for efficiency, and
+ * the iterator implementation will need to be more complex, as in
+ * qpzone.
*/
typedef struct qpc_dbit {
dns_dbiterator_t common;
* Delete the corresponding node from the auxiliary NSEC
* tree before deleting from the main tree.
*/
- result = dns_qp_deletename(qpdb->nsec, &node->name,
+ result = dns_qp_deletename(qpdb->tree, &node->name,
DNS_DBNAMESPACE_NSEC, NULL,
NULL);
if (result != ISC_R_SUCCESS) {
node->nspace, NULL, NULL);
break;
case DNS_DBNAMESPACE_NSEC:
- result = dns_qp_deletename(qpdb->nsec, &node->name,
+ result = dns_qp_deletename(qpdb->tree, &node->name,
node->nspace, NULL, NULL);
break;
}
dns_slabheader_t *found = NULL, *foundsig = NULL;
/*
- * Look for the node in the auxilary tree.
+ * Look for the node in the auxiliary NSEC namespace.
*/
- result = dns_qp_lookup(search->qpdb->nsec, name, DNS_DBNAMESPACE_NSEC,
+ result = dns_qp_lookup(search->qpdb->tree, name, DNS_DBNAMESPACE_NSEC,
NULL, &iter, NULL, (void **)&node, NULL);
/*
* When DNS_R_PARTIALMATCH or ISC_R_NOTFOUND is returned from
}
/*
- * Lookup the predecessor in the main tree.
+ * Lookup the predecessor in the normal namespace.
*/
node = NULL;
result = dns_qp_getname(search->qpdb->tree, predecessor,
qpcache__destroy(qpcache_t *qpdb) {
unsigned int i;
char buf[DNS_NAME_FORMATSIZE];
- dns_qp_t **treep = NULL;
-
- for (;;) {
- /*
- * pick the next tree to (start to) destroy
- */
- treep = &qpdb->tree;
- if (*treep == NULL) {
- treep = &qpdb->nsec;
- if (*treep == NULL) {
- break;
- }
- }
- dns_qp_destroy(treep);
- INSIST(*treep == NULL);
- }
+ dns_qp_destroy(&qpdb->tree);
if (dns_name_dynamic(&qpdb->common.origin)) {
dns_name_format(&qpdb->common.origin, buf, sizeof(buf));
if (newnsec && !qpnode->havensec) {
qpcnode_t *nsecnode = NULL;
- result = dns_qp_getname(qpdb->nsec, name, DNS_DBNAMESPACE_NSEC,
+ result = dns_qp_getname(qpdb->tree, name, DNS_DBNAMESPACE_NSEC,
(void **)&nsecnode, NULL);
if (result != ISC_R_SUCCESS) {
INSIST(nsecnode == NULL);
nsecnode = new_qpcnode(qpdb, name,
DNS_DBNAMESPACE_NSEC);
- result = dns_qp_insert(qpdb->nsec, nsecnode, 0);
+ result = dns_qp_insert(qpdb->tree, nsecnode, 0);
INSIST(result == ISC_R_SUCCESS);
qpcnode_detach(&nsecnode);
}
}
static unsigned int
-nodecount(dns_db_t *db, dns_dbtree_t tree) {
+nodecount(dns_db_t *db, dns_dbtree_t tree ISC_ATTR_UNUSED) {
qpcache_t *qpdb = (qpcache_t *)db;
dns_qp_memusage_t mu;
isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
REQUIRE(VALID_QPDB(qpdb));
TREE_RDLOCK(&qpdb->tree_lock, &tlocktype);
- switch (tree) {
- case dns_dbtree_main:
- mu = dns_qp_memusage(qpdb->tree);
- break;
- case dns_dbtree_nsec:
- mu = dns_qp_memusage(qpdb->nsec);
- break;
- default:
- UNREACHABLE();
- }
+ mu = dns_qp_memusage(qpdb->tree);
TREE_UNLOCK(&qpdb->tree_lock, &tlocktype);
return mu.leaves;
dns_name_dup(origin, mctx, &qpdb->common.origin);
/*
- * Make the qp tries.
+ * Make the qp trie.
*/
dns_qp_create(mctx, &qpmethods, qpdb, &qpdb->tree);
- dns_qp_create(mctx, &qpmethods, qpdb, &qpdb->nsec);
qpdb->common.magic = DNS_DB_MAGIC;
qpdb->common.impmagic = QPDB_MAGIC;
TREE_RDLOCK(&qpdb->tree_lock, &qpdbiter->tree_locked);
/*
- * If we're being called from dbiterator_next or _prev,
- * then we may need to reinitialize the iterator to the current
- * name. The tree could have changed while it was unlocked,
+ * If we're being called from dbiterator_next, we may need
+ * to reinitialize the iterator to the current name. The
+ * tree could have changed while it was unlocked, which
* would make the iterator traversal inconsistent.
*
* As long as the iterator is holding a reference to
result = dns_qpiter_next(&qpdbiter->iter, NULL,
(void **)&qpdbiter->node, NULL);
- if (result == ISC_R_SUCCESS) {
+ if (result == ISC_R_SUCCESS &&
+ qpdbiter->node->nspace == DNS_DBNAMESPACE_NORMAL)
+ {
dns_name_copy(&qpdbiter->node->name, qpdbiter->name);
reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
+ } else if (result == ISC_R_SUCCESS) {
+ result = ISC_R_NOMORE;
+ qpdbiter->node = NULL;
} else {
- INSIST(result == ISC_R_NOMORE); /* The tree is empty. */
+ /* The tree is empty. */
+ INSIST(result == ISC_R_NOMORE);
qpdbiter->node = NULL;
}
result = dns_qpiter_next(&qpdbiter->iter, NULL,
(void **)&qpdbiter->node, NULL);
- if (result == ISC_R_SUCCESS) {
+ if (result == ISC_R_SUCCESS &&
+ qpdbiter->node->nspace == DNS_DBNAMESPACE_NORMAL)
+ {
dns_name_copy(&qpdbiter->node->name, qpdbiter->name);
reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
+ } else if (result == ISC_R_SUCCESS) {
+ result = ISC_R_NOMORE;
+ qpdbiter->node = NULL;
} else {
INSIST(result == ISC_R_NOMORE);
qpdbiter->node = NULL;
}
/*
- * Find node of the NSEC/NSEC3 record that is 'name'.
+ * Find node of the NSEC/NSEC3 record preceding 'name'.
*/
static isc_result_t
previous_closest_nsec(dns_rdatatype_t type, qpz_search_t *search,
for (;;) {
if (*firstp) {
/*
- * Construct the name of the second node to check.
- * It is the first node sought in the NSEC tree.
+ * This is the first attempt to find 'name' in the
+ * NSEC namespace.
*/
*firstp = false;
result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NSEC,
INSIST(result != ISC_R_NOTFOUND);
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.
+ * If we find an exact match in the NSEC
+ * namespace on our first attempt, it
+ * implies that the corresponding node in
+ * the normal namespace had an unacceptable
+ * NSEC record; we want the previous node
+ * in the NSEC tree.
*/
result = dns_qpiter_prev(nit, name, NULL, NULL);
} else if (result == DNS_R_PARTIALMATCH) {
/*
- * The iterator is already where we want it.
+ * This was a partial match, so the
+ * iterator is already at the previous
+ * node in the NSEC namespace, which is
+ * what we want.
*/
dns_qpiter_current(nit, name, NULL, NULL);
result = ISC_R_SUCCESS;
}
} 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.
+ * We've taken at least two steps back through the
+ * NSEC namespace. The previous steps must have
+ * found nodes with NSEC records, but they didn't
+ * work; perhaps they lacked signature records.
+ * Keep searching.
*/
result = dns_qpiter_prev(nit, name, NULL, NULL);
}
}
/*
- * 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.
+ * There should always be a node in the normal namespace
+ * with the same name as the node in the NSEC namespace,
+ * except when nodes in the NSEC namespace are awaiting
+ * deletion.
*/
if (result != DNS_R_PARTIALMATCH && result != ISC_R_NOTFOUND) {
isc_log_write(DNS_LOGCATEGORY_DATABASE,
}
/*
- * Find the NSEC/NSEC3 which is or before the current point on the
- * search chain. For NSEC3 records only NSEC3 records that match the
+ * Find the NSEC/NSEC3 which is at or before the name being sought.
+ * For NSEC3 records only NSEC3 records that match the
* current NSEC3PARAM record are considered.
*/
static isc_result_t
bool need_sig = secure;
/*
- * Use the auxiliary tree only starting with the second node in the
- * hope that the original node will be right much of the time.
+ * When a lookup is unsuccessful, the QP iterator will already
+ * be pointing at the node preceding the searched-for name in
+ * the normal namespace. We'll check there first, assuming it will
+ * be right much of the time. If we don't find an NSEC there,
+ * then we start using the auxiliary NSEC namespace to find
+ * the next predecessor.
*/
result = dns_qpiter_current(&search->iter, name, (void **)&node, NULL);
if (result != ISC_R_SUCCESS) {