Permalink
Browse files

fix pruning of not-recently-used rate limiting buckets

  • Loading branch information...
1 parent b35d5dd commit 765a98cd75234f92fb4fac51b4455999eb456e37 @ccutrer committed Mar 19, 2013
Showing with 23 additions and 11 deletions.
  1. +23 −11 mordor/rate_limiter.h
View
@@ -37,28 +37,39 @@ class RateLimiter
m_timeLimit(timeLimit)
{}
+ ~RateLimiter()
+ {
+ for(typename std::map<T, Bucket>::iterator it(m_buckets.begin());
+ it != m_buckets.end();
+ ++it) {
+ if (it->second.m_timer)
+ it->second.m_timer->cancel();
+ }
+ }
+
bool allowed(const T &key)
{
boost::mutex::scoped_lock lock(m_mutex);
unsigned long long now = m_timerManager.now();
Bucket &bucket = m_buckets[key];
size_t countLimit = m_countLimit->val();
- trim(bucket, now, countLimit);
+ unsigned long long timeLimit = m_timeLimit->val();
+ trim(bucket, now, countLimit, timeLimit);
if (bucket.m_count >= countLimit) {
- startTimer(key, bucket);
+ startTimer(key, bucket, now, timeLimit);
return false;
}
bucket.m_timestamps.push_back(now);
++bucket.m_count;
- startTimer(key, bucket);
+ startTimer(key, bucket, now, timeLimit);
MORDOR_ASSERT(bucket.m_count == bucket.m_timestamps.size());
return true;
}
void reset(const T &key)
{
boost::mutex::scoped_lock lock(m_mutex);
- std::map<T, Bucket>::iterator it = m_buckets.find(key);
+ typename std::map<T, Bucket>::iterator it = m_buckets.find(key);
if (it != m_buckets.end()) {
if (it->second.m_timer)
it->second.m_timer->cancel();
@@ -71,13 +82,14 @@ class RateLimiter
{
boost::mutex::scoped_lock lock(m_mutex);
Bucket &bucket = m_buckets[key];
- trim(bucket, m_timerManager.now());
- startTimer(key, bucket, m_countLimit->val());
+ unsigned long long now = m_timerManager.now();
+ unsigned long long timeLimit = m_timeLimit->val();
+ trim(bucket, now, m_countLimit->val(), timeLimit);
+ startTimer(key, bucket, now, timeLimit);
}
- void trim(Bucket &bucket, unsigned long long now, size_t countLimit)
+ void trim(Bucket &bucket, unsigned long long now, size_t countLimit, unsigned long long timeLimit)
{
- unsigned long long timeLimit = m_timeLimit->val();
MORDOR_ASSERT(bucket.m_count == bucket.m_timestamps.size());
while(!bucket.m_timestamps.empty() && (bucket.m_timestamps.front() < now - timeLimit || bucket.m_count > countLimit))
{
@@ -96,13 +108,13 @@ class RateLimiter
}
}
- void startTimer(const T &key, Bucket &bucket)
+ void startTimer(const T &key, Bucket &bucket, unsigned long long now, unsigned long long timeLimit)
{
// If there are still timestamps, set a timer to clear it
if(!bucket.m_timestamps.empty()) {
if (!bucket.m_timer) {
- //bucket.m_timer = m_timerManager.registerTimer(bucket.m_timestamps.front() + timeLimit - now,
- // boost::bind(&RateLimiter::trimKey, this, key));
+ bucket.m_timer = m_timerManager.registerTimer(bucket.m_timestamps.front() + timeLimit - now,
+ boost::bind(&RateLimiter::trimKey, this, key));
}
} else {
m_buckets.erase(key);

0 comments on commit 765a98c

Please sign in to comment.