mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
Improve performance for delegation heavy answers and also general query performance (#44029)
This commit is contained in:
@@ -6,8 +6,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <config.h>
|
||||
@@ -190,18 +188,16 @@ static dns_rdatasetmethods_t question_methods = {
|
||||
question_current,
|
||||
question_clone,
|
||||
question_count,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
NULL, /* addnoqname */
|
||||
NULL, /* getnoqname */
|
||||
NULL, /* addclosest */
|
||||
NULL, /* getclosest */
|
||||
NULL, /* settrust */
|
||||
NULL, /* expire */
|
||||
NULL, /* clearprefetch */
|
||||
NULL, /* setownercase */
|
||||
NULL, /* getownercase */
|
||||
NULL /* addglue */
|
||||
};
|
||||
|
||||
void
|
||||
@@ -293,6 +289,7 @@ dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
|
||||
#define MAX_SHUFFLE 32
|
||||
#define WANT_FIXED(r) (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0)
|
||||
#define WANT_RANDOM(r) (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0)
|
||||
#define WANT_CYCLIC(r) (((r)->attributes & DNS_RDATASETATTR_CYCLIC) != 0)
|
||||
|
||||
struct towire_sort {
|
||||
int key;
|
||||
@@ -320,9 +317,11 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
|
||||
isc_buffer_t savedbuffer, rdlen, rrbuffer;
|
||||
unsigned int headlen;
|
||||
isc_boolean_t question = ISC_FALSE;
|
||||
isc_boolean_t shuffle = ISC_FALSE;
|
||||
dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE];
|
||||
struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE];
|
||||
isc_boolean_t shuffle = ISC_FALSE, sort = ISC_FALSE;
|
||||
dns_rdata_t orig_fixed[MAX_SHUFFLE];
|
||||
dns_rdata_t *orig = orig_fixed;
|
||||
struct towire_sort new_fixed[MAX_SHUFFLE];
|
||||
struct towire_sort *new = new_fixed;
|
||||
dns_fixedname_t fixed;
|
||||
dns_name_t *name;
|
||||
|
||||
@@ -363,53 +362,43 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
|
||||
}
|
||||
|
||||
/*
|
||||
* Do we want to shuffle this answer?
|
||||
* Do we want to sort and/or shuffle this answer?
|
||||
*/
|
||||
if (!question && count > 1 &&
|
||||
(!WANT_FIXED(rdataset) || order != NULL) &&
|
||||
rdataset->type != dns_rdatatype_rrsig)
|
||||
shuffle = ISC_TRUE;
|
||||
|
||||
if (shuffle && count > MAX_SHUFFLE) {
|
||||
shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled));
|
||||
sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted));
|
||||
if (shuffled == NULL || sorted == NULL)
|
||||
shuffle = ISC_FALSE;
|
||||
} else {
|
||||
shuffled = shuffled_fixed;
|
||||
sorted = sorted_fixed;
|
||||
if (!question && count > 1 && rdataset->type != dns_rdatatype_rrsig) {
|
||||
if (order != NULL) {
|
||||
sort = ISC_TRUE;
|
||||
}
|
||||
if (WANT_RANDOM(rdataset) || WANT_CYCLIC(rdataset)) {
|
||||
shuffle = ISC_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (shuffle) {
|
||||
if ((shuffle || sort) && count > MAX_SHUFFLE) {
|
||||
orig = isc_mem_get(cctx->mctx, count * sizeof(*orig));
|
||||
new = isc_mem_get(cctx->mctx, count * sizeof(*new));
|
||||
if (orig == NULL || new == NULL)
|
||||
shuffle = sort = ISC_FALSE;
|
||||
}
|
||||
|
||||
if (shuffle || sort) {
|
||||
/*
|
||||
* First we get handles to all of the rdata.
|
||||
*/
|
||||
i = 0;
|
||||
do {
|
||||
INSIST(i < count);
|
||||
dns_rdata_init(&shuffled[i]);
|
||||
dns_rdataset_current(rdataset, &shuffled[i]);
|
||||
dns_rdata_init(&orig[i]);
|
||||
dns_rdataset_current(rdataset, &orig[i]);
|
||||
i++;
|
||||
result = dns_rdataset_next(rdataset);
|
||||
} while (result == ISC_R_SUCCESS);
|
||||
if (result != ISC_R_NOMORE)
|
||||
goto cleanup;
|
||||
INSIST(i == count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we shuffle.
|
||||
*/
|
||||
if (WANT_FIXED(rdataset)) {
|
||||
/*
|
||||
* 'Fixed' order.
|
||||
*/
|
||||
INSIST(order != NULL);
|
||||
for (i = 0; i < count; i++) {
|
||||
sorted[i].key = (*order)(&shuffled[i],
|
||||
order_arg);
|
||||
sorted[i].rdata = &shuffled[i];
|
||||
}
|
||||
} else if (WANT_RANDOM(rdataset)) {
|
||||
if (shuffle) {
|
||||
if (WANT_RANDOM(rdataset)) {
|
||||
/*
|
||||
* 'Random' order.
|
||||
*/
|
||||
@@ -418,19 +407,19 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
|
||||
|
||||
isc_random_get(&val);
|
||||
choice = i + (val % (count - i));
|
||||
rdata = shuffled[i];
|
||||
shuffled[i] = shuffled[choice];
|
||||
shuffled[choice] = rdata;
|
||||
rdata = orig[i];
|
||||
orig[i] = orig[choice];
|
||||
orig[choice] = rdata;
|
||||
if (order != NULL)
|
||||
sorted[i].key = (*order)(&shuffled[i],
|
||||
new[i].key = (*order)(&orig[i],
|
||||
order_arg);
|
||||
else
|
||||
sorted[i].key = 0; /* Unused */
|
||||
sorted[i].rdata = &shuffled[i];
|
||||
new[i].key = 0; /* Unused */
|
||||
new[i].rdata = &orig[i];
|
||||
}
|
||||
} else {
|
||||
} else if (WANT_CYCLIC(rdataset)) {
|
||||
/*
|
||||
* "Cyclic" order.
|
||||
* 'Cyclic' order.
|
||||
*/
|
||||
isc_uint32_t val;
|
||||
unsigned int j;
|
||||
@@ -441,23 +430,31 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
|
||||
j = val % count;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (order != NULL)
|
||||
sorted[i].key = (*order)(&shuffled[j],
|
||||
new[i].key = (*order)(&orig[j],
|
||||
order_arg);
|
||||
else
|
||||
sorted[i].key = 0; /* Unused */
|
||||
sorted[i].rdata = &shuffled[j];
|
||||
new[i].key = 0; /* Unused */
|
||||
new[i].rdata = &orig[j];
|
||||
j++;
|
||||
if (j == count)
|
||||
j = 0; /* Wrap around. */
|
||||
}
|
||||
}
|
||||
} else if (sort) {
|
||||
for (i = 0; i < count; i++) {
|
||||
if (order != NULL)
|
||||
new[i].key = (*order)(&orig[i], order_arg);
|
||||
else
|
||||
new[i].key = 0; /* Unused */
|
||||
new[i].rdata = &orig[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sorted order.
|
||||
*/
|
||||
if (order != NULL)
|
||||
qsort(sorted, count, sizeof(sorted[0]),
|
||||
towire_compare);
|
||||
/*
|
||||
* Sortlist order.
|
||||
*/
|
||||
if (sort) {
|
||||
qsort(new, count, sizeof(new[0]), towire_compare);
|
||||
}
|
||||
|
||||
savedbuffer = *target;
|
||||
@@ -502,9 +499,9 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
|
||||
/*
|
||||
* Copy out the rdata
|
||||
*/
|
||||
if (shuffle)
|
||||
rdata = *(sorted[i].rdata);
|
||||
else {
|
||||
if (shuffle || sort) {
|
||||
rdata = *(new[i].rdata);
|
||||
} else {
|
||||
dns_rdata_reset(&rdata);
|
||||
dns_rdataset_current(rdataset, &rdata);
|
||||
}
|
||||
@@ -519,7 +516,7 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
|
||||
added++;
|
||||
}
|
||||
|
||||
if (shuffle) {
|
||||
if (shuffle || sort) {
|
||||
i++;
|
||||
if (i == count)
|
||||
result = ISC_R_NOMORE;
|
||||
@@ -552,10 +549,10 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
|
||||
*target = savedbuffer;
|
||||
|
||||
cleanup:
|
||||
if (sorted != NULL && sorted != sorted_fixed)
|
||||
isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted));
|
||||
if (shuffled != NULL && shuffled != shuffled_fixed)
|
||||
isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled));
|
||||
if (new != NULL && new != new_fixed)
|
||||
isc_mem_put(cctx->mctx, new, count * sizeof(*new));
|
||||
if (orig != NULL && orig != orig_fixed)
|
||||
isc_mem_put(cctx->mctx, orig, count * sizeof(*orig));
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -680,83 +677,6 @@ dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
|
||||
return((rdataset->methods->getclosest)(rdataset, name, neg, negsig));
|
||||
}
|
||||
|
||||
/*
|
||||
* Additional cache stuff
|
||||
*/
|
||||
isc_result_t
|
||||
dns_rdataset_getadditional(dns_rdataset_t *rdataset,
|
||||
dns_rdatasetadditional_t type,
|
||||
dns_rdatatype_t qtype,
|
||||
dns_acache_t *acache,
|
||||
dns_zone_t **zonep,
|
||||
dns_db_t **dbp,
|
||||
dns_dbversion_t **versionp,
|
||||
dns_dbnode_t **nodep,
|
||||
dns_name_t *fname,
|
||||
dns_message_t *msg,
|
||||
isc_stdtime_t now)
|
||||
{
|
||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||
REQUIRE(rdataset->methods != NULL);
|
||||
REQUIRE(zonep == NULL || *zonep == NULL);
|
||||
REQUIRE(dbp != NULL && *dbp == NULL);
|
||||
REQUIRE(versionp != NULL && *versionp == NULL);
|
||||
REQUIRE(nodep != NULL && *nodep == NULL);
|
||||
REQUIRE(fname != NULL);
|
||||
REQUIRE(msg != NULL);
|
||||
|
||||
if (acache != NULL && rdataset->methods->getadditional != NULL) {
|
||||
return ((rdataset->methods->getadditional)(rdataset, type,
|
||||
qtype, acache,
|
||||
zonep, dbp,
|
||||
versionp, nodep,
|
||||
fname, msg, now));
|
||||
}
|
||||
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_rdataset_setadditional(dns_rdataset_t *rdataset,
|
||||
dns_rdatasetadditional_t type,
|
||||
dns_rdatatype_t qtype,
|
||||
dns_acache_t *acache,
|
||||
dns_zone_t *zone,
|
||||
dns_db_t *db,
|
||||
dns_dbversion_t *version,
|
||||
dns_dbnode_t *node,
|
||||
dns_name_t *fname)
|
||||
{
|
||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||
REQUIRE(rdataset->methods != NULL);
|
||||
|
||||
if (acache != NULL && rdataset->methods->setadditional != NULL) {
|
||||
return ((rdataset->methods->setadditional)(rdataset, type,
|
||||
qtype, acache, zone,
|
||||
db, version,
|
||||
node, fname));
|
||||
}
|
||||
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_rdataset_putadditional(dns_acache_t *acache,
|
||||
dns_rdataset_t *rdataset,
|
||||
dns_rdatasetadditional_t type,
|
||||
dns_rdatatype_t qtype)
|
||||
{
|
||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||
REQUIRE(rdataset->methods != NULL);
|
||||
|
||||
if (acache != NULL && rdataset->methods->putadditional != NULL) {
|
||||
return ((rdataset->methods->putadditional)(acache, rdataset,
|
||||
type, qtype));
|
||||
}
|
||||
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
|
||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||
@@ -830,3 +750,20 @@ dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
|
||||
rdataset->ttl = ttl;
|
||||
sigrdataset->ttl = ttl;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_rdataset_addglue(dns_rdataset_t *rdataset,
|
||||
dns_dbversion_t *version,
|
||||
unsigned int options,
|
||||
dns_message_t *msg)
|
||||
{
|
||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||
REQUIRE(rdataset->methods != NULL);
|
||||
REQUIRE(rdataset->type == dns_rdatatype_ns);
|
||||
|
||||
if (rdataset->methods->addglue == NULL)
|
||||
return (ISC_R_NOTIMPLEMENTED);
|
||||
|
||||
return ((rdataset->methods->addglue)(rdataset, version,
|
||||
options, msg));
|
||||
}
|
||||
|
Reference in New Issue
Block a user