Files
libucore/include/ucore/rate_limit.h
T
2013-10-15 15:03:27 +02:00

101 lines
3.2 KiB
C

#ifndef UC_RATE_LIMIT_H_
#define UC_RATE_LIMIT_H_
/** This is a rate limiter, based on the token bucket principle.
* We have X amount of tickets(=our rate) per Y amount of time,
*
* The allowed tickets increases with X per Y amount of time.
*
* Bursts will be allowed up till the number of tickets initially
* specified.
* e.g. if we are limited to 50 tickets * per 2 second, 50 tickets
* can be immedietely handed out in the
* first second. At the 2. second, 25 more tickets become available
* handed out, at the 3. second 25 more, and so on.
* (So this is throttleed, so no more than the initial tickets, 50 in
* this case, can be handed out in any given period)
*
* Another example is if we rate 1000 tickets per 60 seconds,
* 1000 tickets can be handed out the 1. second, 16/17 more the
* next second, 16/17 more the 3. second and so on.
*
* Specify how many tickes we have available per period of time.
* when work is performed, call uc_ratelimit_cllow() with the current
* time.
* The unit of time passed to uc_ratelimit_allow must be the same as
* for uc_ratelimit_init.
*
* Example for rate limiting accepting connections:
* struct RateLimit r;
* //Limit to 20 per 1 second, which also limits us to max 20
* per second. (1 second since we will pass in time that have 1 second resolution)
* 40 per 2 second would even out to the same rate, but allow a burst of 40
* (if there's 40 tickets available)
*
* uc_ratelimit_init(&r,20, 1, time(NULL));
*
* NOTE. period * tickets * 2 must not exceed the value of a long
*
* for (;;) {
* int fd = accept(..);
* if (uc_ratelimit_allow(&r, time(NULL)) {
* //handle new connection
* } else {
* //exceeded limit
* close(fd);
* }
* }
*/
struct RateLimit {
//how many tickets we want
long tickets;
//per this period of time
long period;
//internal fields:
//how much each ticket is worth.
long ticket_cost;
//money we have to "buy" tickets
long funds;
//time of the previos period
long last_ts;
};
/**
* Initialize a struct RateLimit, which can hand out @tickets per @period
* the perioid must be in the same units as the current_ts
*
* NOTE. period * tickets * 2 must not exceed the range of the RateLimit.funds
*
* @param r RateLimit to initialize
* @param tickets number of tickets (bucket depth)
* @param period per this period
* @param current_ts the current timestamp
*/
void uc_ratelimit_init(struct RateLimit *r, long tickets, long period, long current_ts);
/**
* Reset a RateLimit, filling up the tickets again.
*
* @param r RateLimit to reset
* @param current ts, if non-zero, re-sets the last_ts to the current_ts
*/
void uc_ratelimit_reset(struct RateLimit *r, long current_ts);
/**
* Check if we have 1 ticket available, and can therefore allow
* the work. Removes 1 ticket if we can, and replenishes the tickets
* based on the elapsed time since last time the function was called.
*
* @param r the RateLimit
* @param current_ts the current timestamp. Used to calculate the
* replenisment of tichets since the previous check.
* @return 1 if we can allow, 0 if we don't.
*/
int uc_ratelimit_allow(struct RateLimit *r, long current_ts);
#endif