]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Refactor code around random/cyclic/fixed to reduce code duplication
authorOndřej Surý <ondrej@sury.org>
Sun, 5 Aug 2018 05:18:27 +0000 (07:18 +0200)
committerOndřej Surý <ondrej@sury.org>
Mon, 6 Aug 2018 09:24:14 +0000 (11:24 +0200)
lib/dns/rdataset.c

index afe76e16dd91f87b50ec13cb00e9284649e354e9..b8a66af3b2dff967b392d776ea0198eb36c2f3d4 100644 (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,70 +409,44 @@ 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;
+               unsigned int j, seed;
+               if (ISC_LIKELY(want_random)) {
+                       seed = isc_random32();
+                       j = 0;
+               }
 
-                       val = rdataset->count;
-                       if (val == ISC_UINT32_MAX) {
-                               val = isc_random32();
+               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 (ISC_LIKELY(want_random)) {
+                               swap_rdata(in, j, j + seed % (count - j));
                        }
-                       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. */
+
+                       out[i].key = (sort) ?
+                               (*order)(&in[j], order_arg) :
+                               0;
+                       out[i].rdata = &in[j];
+                       if (++j == count) {
+                               j = 0;
                        }
                }
-       } else if (sort) {
-               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];
+               /*
+                * Sortlist order.
+                */
+               if (sort) {
+                       qsort(out, count, sizeof(out[0]), towire_compare);
                }
        }
 
-       /*
-        * Sortlist order.
-        */
-       if (sort) {
-               qsort(out, count, sizeof(out[0]), towire_compare);
-       }
-
        savedbuffer = *target;
        i = 0;
        added = 0;
@@ -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);
 
                        /*