#include "ucore/rate_limit.h" #define SCALE_FACTOR 1000 void uc_ratelimit_init(struct RateLimit *r, long tickets, long period, long current_ts) { r->tickets = tickets; r->scaled_tickets = tickets * SCALE_FACTOR; r->period = period; r->available_tickets = r->scaled_tickets; r->last_ts = current_ts; } void uc_ratelimit_reset(struct RateLimit *r, long current_ts) { r->available_tickets = r->scaled_tickets; if (current_ts) r->last_ts = current_ts; } int uc_ratelimit_allow(struct RateLimit *r, long current_ts) { int allowed; long diff_period; //Find elapsed time diff_period = current_ts - r->last_ts; //If time went backwards, we halt the time for this round if (diff_period < 0) diff_period = 0; //Calculate the number of tickets that became available since //the last time. (+ ScALE_FACTOR/2 is to round up at halfway points for //integer arithmetics) r->available_tickets += diff_period * ((r->scaled_tickets + SCALE_FACTOR/2) / r->period); //throttle handing out tickets // if (r->available_tickets > r->scaled_tickets) r->available_tickets = r->scaled_tickets; //If we have at least onen ticket, we can allow if (r->available_tickets >= 1 * SCALE_FACTOR) { r->available_tickets -= 1 * SCALE_FACTOR; allowed = 1; } else { //no more tickets. allowed = 0; } //save this period. r->last_ts = current_ts; return allowed; } #if 0 int main() { int i; struct RateLimit r; time_t start; uc_ratelimit_init(&r, 10, 60, time(NULL)); for(i = 0; i < 120; i++) { int k; long allowed = 0; sleep(1); for (k = 0; k < 500; k++) allowed += uc_ratelimit_allow(&r, time(NULL)); printf("%ld of 500 can pass\n", allowed); } return 0; } #endif