Refactor code around random/cyclic/fixed to reduce code duplication

This commit is contained in:
Ondřej Surý
2018-08-05 07:18:27 +02:00
parent f7986c8d1a
commit 41a68425ea

View File

@@ -306,6 +306,14 @@ towire_compare(const void *av, const void *bv) {
return (a->key - b->key);
}
static inline void
swap_rdata(dns_rdata_t *in, unsigned int a, unsigned int b) {
dns_rdata_t rdata = DNS_RDATA_INIT;
rdata = in[a];
in[a] = in[b];
in[b] = rdata;
}
static isc_result_t
towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
dns_compress_t *cctx, isc_buffer_t *target,
@@ -313,10 +321,9 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
isc_boolean_t partial, unsigned int options,
unsigned int *countp, void **state)
{
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_region_t r;
isc_result_t result;
unsigned int i, count = 0, added, choice;
unsigned int i, count = 0, added;
isc_buffer_t savedbuffer, rdlen, rrbuffer;
unsigned int headlen;
isc_boolean_t question = ISC_FALSE;
@@ -380,14 +387,17 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
}
}
if ((shuffle || sort) && count > MAX_SHUFFLE) {
in = isc_mem_get(cctx->mctx, count * sizeof(*in));
out = isc_mem_get(cctx->mctx, count * sizeof(*out));
if (in == NULL || out == NULL)
shuffle = sort = ISC_FALSE;
if ((shuffle || sort)) {
if (count > MAX_SHUFFLE) {
in = isc_mem_get(cctx->mctx, count * sizeof(*in));
out = isc_mem_get(cctx->mctx, count * sizeof(*out));
if (in == NULL || out == NULL) {
shuffle = sort = ISC_FALSE;
}
}
}
if (shuffle || sort) {
if ((shuffle || sort)) {
/*
* First we get handles to all of the rdata.
*/
@@ -399,68 +409,42 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
i++;
result = dns_rdataset_next(rdataset);
} while (result == ISC_R_SUCCESS);
if (result != ISC_R_NOMORE)
if (result != ISC_R_NOMORE) {
goto cleanup;
}
INSIST(i == count);
}
if (shuffle) {
if (want_random) {
/*
* 'Random' order.
*/
isc_uint32_t val = isc_random32();
for (i = 0; i < count; i++) {
choice = i + val % (count - i);
rdata = in[i];
in[i] = in[choice];
in[choice] = rdata;
if (order != NULL)
out[i].key = (*order)(&in[i],
order_arg);
else
out[i].key = 0; /* Unused */
out[i].rdata = &in[i];
}
} else if (want_cyclic) {
/*
* 'Cyclic' order.
*/
isc_uint32_t val;
unsigned int j;
val = rdataset->count;
if (val == ISC_UINT32_MAX) {
val = isc_random32();
}
j = val % count;
for (i = 0; i < count; i++) {
if (order != NULL)
out[i].key = (*order)(&in[j],
order_arg);
else
out[i].key = 0; /* Unused */
out[i].rdata = &in[j];
j++;
if (j == count)
j = 0; /* Wrap around. */
}
unsigned int j, seed;
if (ISC_LIKELY(want_random)) {
seed = isc_random32();
j = 0;
}
} else if (sort) {
if (ISC_UNLIKELY(want_cyclic) && (rdataset->count < ISC_UINT32_MAX)) {
j = rdataset->count % count;
} else { /* Otherwise, just start from beginning */
j = 0;
}
for (i = 0; i < count; i++) {
if (order != NULL)
out[i].key = (*order)(&in[i], order_arg);
else
out[i].key = 0; /* Unused */
out[i].rdata = &in[i];
}
}
if (ISC_LIKELY(want_random)) {
swap_rdata(in, j, j + seed % (count - j));
}
/*
* Sortlist order.
*/
if (sort) {
qsort(out, count, sizeof(out[0]), towire_compare);
out[i].key = (sort) ?
(*order)(&in[j], order_arg) :
0;
out[i].rdata = &in[j];
if (++j == count) {
j = 0;
}
}
/*
* Sortlist order.
*/
if (sort) {
qsort(out, count, sizeof(out[0]), towire_compare);
}
}
savedbuffer = *target;
@@ -497,6 +481,8 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
isc_buffer_putuint16(target, rdataset->type);
isc_buffer_putuint16(target, rdataset->rdclass);
if (!question) {
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_buffer_putuint32(target, rdataset->ttl);
/*