int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, uint64_t available) { unsigned h; JournalRateLimitGroup *g; JournalRateLimitPool *p; unsigned burst; usec_t ts; assert(id); if (!r) return 1; if (r->interval == 0 || r->burst == 0) return 1; burst = burst_modulate(r->burst, available); ts = now(CLOCK_MONOTONIC); h = string_hash_func(id); g = r->buckets[h % BUCKETS_MAX]; LIST_FOREACH(bucket, g, g) if (streq(g->id, id)) break; if (!g) { g = journal_rate_limit_group_new(r, id, ts); if (!g) return -ENOMEM; } p = &g->pools[priority_map[priority]]; if (p->begin <= 0) { p->suppressed = 0; p->num = 1; p->begin = ts; return 1; } if (p->begin + r->interval < ts) { unsigned s; s = p->suppressed; p->suppressed = 0; p->num = 1; p->begin = ts; return 1 + s; } if (p->num <= burst) { p->num++; return 1; } p->suppressed++; return 0; }
int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, uint64_t available) { uint64_t h; JournalRateLimitGroup *g; JournalRateLimitPool *p; struct siphash state; unsigned burst; usec_t ts; assert(id); /* Returns: * * 0 → the log message shall be suppressed, * 1 + n → the log message shall be permitted, and n messages were dropped from the peer before * < 0 → error */ if (!r) return 1; if (r->interval == 0 || r->burst == 0) return 1; burst = burst_modulate(r->burst, available); ts = now(CLOCK_MONOTONIC); siphash24_init(&state, r->hash_key); string_hash_func(id, &state); h = siphash24_finalize(&state); g = r->buckets[h % BUCKETS_MAX]; LIST_FOREACH(bucket, g, g) if (streq(g->id, id)) break; if (!g) { g = journal_rate_limit_group_new(r, id, ts); if (!g) return -ENOMEM; } p = &g->pools[priority_map[priority]]; if (p->begin <= 0) { p->suppressed = 0; p->num = 1; p->begin = ts; return 1; } if (p->begin + r->interval < ts) { unsigned s; s = p->suppressed; p->suppressed = 0; p->num = 1; p->begin = ts; return 1 + s; } if (p->num < burst) { p->num++; return 1; } p->suppressed++; return 0; }