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