From: Vladimír Čunát Date: Mon, 17 Sep 2018 13:54:01 +0000 (+0200) Subject: add kr_random_coin() to make some code more readable X-Git-Tag: v3.2.0~13^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f8867141dbeb24ffad44a1059f9a4596eeae1c7c;p=thirdparty%2Fknot-resolver.git add kr_random_coin() to make some code more readable --- diff --git a/lib/nsrep.c b/lib/nsrep.c index cf08c71a5..ab46eea68 100644 --- a/lib/nsrep.c +++ b/lib/nsrep.c @@ -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); diff --git a/lib/utils.h b/lib/utils.h index 448842005..fc435bb78 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -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); diff --git a/modules/stats/stats.c b/modules/stats/stats.c index 5f5139de6..32c02219d 100644 --- a/modules/stats/stats.c +++ b/modules/stats/stats.c @@ -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);