2
0
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:
Mukund Sivaraman
2017-04-22 08:25:10 +05:30
parent 4c31eda5e1
commit 03be5a6b4e
134 changed files with 1619 additions and 4420 deletions

View File

@@ -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));
}