(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);
/** 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);
}
/* 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);