forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrecent_lookups.cc
60 lines (52 loc) · 1.46 KB
/
recent_lookups.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include "source/common/stats/recent_lookups.h"
#include "source/common/common/assert.h"
namespace Envoy {
namespace Stats {
void RecentLookups::lookup(absl::string_view str) {
++total_;
if (capacity_ == 0) {
return;
}
auto map_iter = map_.find(str);
if (map_iter != map_.end()) {
// The item is already in the list. Bump its reference-count and move it to
// the front of the list.
auto list_iter = map_iter->second;
++list_iter->count_;
if (list_iter != list_.begin()) {
list_.splice(list_.begin(), list_, list_iter);
}
} else {
ASSERT(list_.size() <= capacity_);
// Evict oldest item if needed.
if (list_.size() >= capacity_) {
evictOne();
}
// The string storage is in the list entry.
list_.push_front(ItemCount{std::string(str), 1});
auto list_iter = list_.begin();
map_[list_iter->item_] = list_iter;
}
ASSERT(list_.size() == map_.size());
}
void RecentLookups::forEach(const IterFn& fn) const {
for (const ItemCount& item_count : list_) {
fn(item_count.item_, item_count.count_);
}
}
void RecentLookups::setCapacity(uint64_t capacity) {
capacity_ = capacity;
while (capacity_ < list_.size()) {
evictOne();
}
}
void RecentLookups::evictOne() {
ASSERT(!list_.empty());
ASSERT(!map_.empty());
const ItemCount& item_count = list_.back();
int erased = map_.erase(item_count.item_);
ASSERT(erased == 1);
list_.pop_back();
}
} // namespace Stats
} // namespace Envoy