X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=libevent%2Fbufferevent_ratelim.c;h=7965390ee66be91217b90de9bf0c6ce30538e4ff;hp=85904e828bde3a85f089304df7042a640a269ddd;hb=3a84db87064922ad10ac10cc1d6833380e575995;hpb=b0bcb8f6b0571592a50ce039882c9319e012a270 diff --git a/libevent/bufferevent_ratelim.c b/libevent/bufferevent_ratelim.c index 85904e82..7965390e 100644 --- a/libevent/bufferevent_ratelim.c +++ b/libevent/bufferevent_ratelim.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2010 Niels Provos and Nick Mathewson + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson * Copyright (c) 2002-2006 Niels Provos * All rights reserved. * @@ -43,6 +43,7 @@ #include "bufferevent-internal.h" #include "mm-internal.h" #include "util-internal.h" +#include "event-internal.h" int ev_token_bucket_init(struct ev_token_bucket *bucket, @@ -165,7 +166,8 @@ ev_token_bucket_cfg_new(size_t read_rate, size_t read_burst, r->read_maximum = read_burst; r->write_maximum = write_burst; memcpy(&r->tick_timeout, tick_len, sizeof(struct timeval)); - r->msec_per_tick = (tick_len->tv_sec * 1000) + tick_len->tv_usec/1000; + r->msec_per_tick = (tick_len->tv_sec * 1000) + + (tick_len->tv_usec & COMMON_TIMEOUT_MICROSECONDS_MASK)/1000; return r; } @@ -187,6 +189,8 @@ ev_token_bucket_cfg_free(struct ev_token_bucket_cfg *cfg) static int _bev_group_suspend_reading(struct bufferevent_rate_limit_group *g); static int _bev_group_suspend_writing(struct bufferevent_rate_limit_group *g); +static void _bev_group_unsuspend_reading(struct bufferevent_rate_limit_group *g); +static void _bev_group_unsuspend_writing(struct bufferevent_rate_limit_group *g); /** Helper: figure out the maximum amount we should write if is_write, or the maximum amount we should read if is_read. Return that maximum, or @@ -283,6 +287,10 @@ _bufferevent_decrement_read_buckets(struct bufferevent_private *bev, ev_ssize_t if (event_add(&bev->rate_limiting->refill_bucket_event, &bev->rate_limiting->cfg->tick_timeout) < 0) r = -1; + } else if (bev->read_suspended & BEV_SUSPEND_BW) { + if (!(bev->write_suspended & BEV_SUSPEND_BW)) + event_del(&bev->rate_limiting->refill_bucket_event); + bufferevent_unsuspend_read(&bev->bev, BEV_SUSPEND_BW); } } @@ -292,6 +300,8 @@ _bufferevent_decrement_read_buckets(struct bufferevent_private *bev, ev_ssize_t bev->rate_limiting->group->total_read += bytes; if (bev->rate_limiting->group->rate_limit.read_limit <= 0) { _bev_group_suspend_reading(bev->rate_limiting->group); + } else if (bev->rate_limiting->group->read_suspended) { + _bev_group_unsuspend_reading(bev->rate_limiting->group); } UNLOCK_GROUP(bev->rate_limiting->group); } @@ -315,6 +325,10 @@ _bufferevent_decrement_write_buckets(struct bufferevent_private *bev, ev_ssize_t if (event_add(&bev->rate_limiting->refill_bucket_event, &bev->rate_limiting->cfg->tick_timeout) < 0) r = -1; + } else if (bev->write_suspended & BEV_SUSPEND_BW) { + if (!(bev->read_suspended & BEV_SUSPEND_BW)) + event_del(&bev->rate_limiting->refill_bucket_event); + bufferevent_unsuspend_write(&bev->bev, BEV_SUSPEND_BW); } } @@ -324,6 +338,8 @@ _bufferevent_decrement_write_buckets(struct bufferevent_private *bev, ev_ssize_t bev->rate_limiting->group->total_written += bytes; if (bev->rate_limiting->group->rate_limit.write_limit <= 0) { _bev_group_suspend_writing(bev->rate_limiting->group); + } else if (bev->rate_limiting->group->write_suspended) { + _bev_group_unsuspend_writing(bev->rate_limiting->group); } UNLOCK_GROUP(bev->rate_limiting->group); } @@ -518,6 +534,7 @@ _bev_group_refill_callback(evutil_socket_t fd, short what, void *arg) event_base_gettimeofday_cached(event_get_base(&g->master_refill_event), &now); LOCK_GROUP(g); + tick = ev_token_bucket_get_tick(&now, &g->rate_limit_cfg); ev_token_bucket_update(&g->rate_limit, &g->rate_limit_cfg, tick); @@ -636,13 +653,15 @@ bufferevent_rate_limit_group_new(struct event_base *base, ev_token_bucket_init(&g->rate_limit, cfg, tick, 0); - g->min_share = 64; event_assign(&g->master_refill_event, base, -1, EV_PERSIST, _bev_group_refill_callback, g); /*XXXX handle event_add failure */ event_add(&g->master_refill_event, &cfg->tick_timeout); EVTHREAD_ALLOC_LOCK(g->lock, EVTHREAD_LOCKTYPE_RECURSIVE); + + bufferevent_rate_limit_group_set_min_share(g, 64); + return g; } @@ -670,6 +689,9 @@ bufferevent_rate_limit_group_set_cfg( event_add(&g->master_refill_event, &cfg->tick_timeout); } + /* The new limits might force us to adjust min_share differently. */ + bufferevent_rate_limit_group_set_min_share(g, g->configured_min_share); + UNLOCK_GROUP(g); return 0; } @@ -682,6 +704,15 @@ bufferevent_rate_limit_group_set_min_share( if (share > EV_SSIZE_MAX) return -1; + g->configured_min_share = share; + + /* Can't set share to less than the one-tick maximum. IOW, at steady + * state, at least one connection can go per tick. */ + if (share > g->rate_limit_cfg.read_rate) + share = g->rate_limit_cfg.read_rate; + if (share > g->rate_limit_cfg.write_rate) + share = g->rate_limit_cfg.write_rate; + g->min_share = share; return 0; }