]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
add kr_random_coin() to make some code more readable
authorVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 17 Sep 2018 13:54:01 +0000 (15:54 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 11 Dec 2018 11:19:43 +0000 (12:19 +0100)
lib/nsrep.c
lib/utils.h
modules/stats/stats.c

index cf08c71a5aec9c286fc6b517ddf14248e67c1984..ab46eea681c95f43cee2b97071eec5bdd8dbcab0 100644 (file)
@@ -255,8 +255,8 @@ static int eval_nsrep(const knot_dname_t *owner, const pack_t *addr_set, struct
           (score < KR_NS_LONG  || qry->flags.NO_THROTTLE)) {
                update_nsrep_set(ns, owner, addr_choice, score);
                ns->reputation = reputation;
-       } else if ((kr_rand_bytes(1) <= 256 / 10) &&
-                  (kr_rand_bytes(2) * KR_NS_MAX_SCORE / (1<<16) >= score)) {
+       } else if (kr_rand_coin(1, 10) &&
+                  !kr_rand_coin(score, KR_NS_MAX_SCORE)) {
                /* With 10% chance probe server with a probability
                 * given by its RTT / MAX_RTT. */
                update_nsrep_set(ns, owner, addr_choice, score);
index 448842005b90f30186196d9d11f98773941820a7..fc435bb7842365a0c035c4fee6b5557fedd21ebb 100644 (file)
@@ -214,6 +214,24 @@ static inline uint64_t kr_rand_bytes(int size)
 /** non-static variant of kr_rand_bytes() */
 KR_EXPORT uint64_t kr_rand_bytes_nonstatic(int size);
 
+/** Throw a pseudo-random coin, succeeding approximately with probability nomin/denomin.
+ * - low precision, only one byte of randomness
+ * - the most extreme bias is 1:255
+ * - tip: use !kr_rand_coin() to get the complementary probability
+ */
+static inline bool kr_rand_coin(int nomin, int denomin)
+{
+       if (nomin < 0 || denomin <= 0 || nomin > denomin) {
+               kr_log_error("kr_rand_coin(): EINVAL\n");
+               abort();
+       }
+       /* threshold = how many parts from 256 are a success */
+       int threshold = (nomin * 256 + /*rounding*/ denomin / 2) / denomin;
+       if (threshold == 0) threshold = 1;
+       if (threshold == 256) threshold = 255;
+       return (kr_rand_bytes(1) < threshold);
+}
+
 /** Memory reservation routine for knot_mm_t */
 KR_EXPORT
 int kr_memreserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have);
index 5f5139de66f975c709d26396daf8c0f78c843070..32c02219d0ebaa82fffb1e1c0d755a1932a9e5ac 100644 (file)
@@ -141,7 +141,7 @@ static void collect_sample(struct stat_data *data, struct kr_rplan *rplan, knot_
                }
                /* Consider 1 in N for frequent sampling.
                 * TODO: redesign the sampling approach. */
-               if (kr_rand_bytes(1) * FREQUENT_PSAMPLE / 256 <= 1) {
+               if (kr_rand_coin(1, FREQUENT_PSAMPLE)) {
                        int key_len = collect_key(key, qry->sname, qry->stype);
                        if (key_len < 0) {
                                assert(false);