1
#include "source/common/config/ttl.h"
2

            
3
namespace Envoy {
4
namespace Config {
5

            
6
TtlManager::TtlManager(std::function<void(const std::vector<std::string>&)> callback,
7
                       Event::Dispatcher& dispatcher, TimeSource& time_source)
8
3305
    : callback_(callback), dispatcher_(dispatcher), time_source_(time_source) {
9
4244
  timer_ = dispatcher_.createTimer([this]() {
10
1365
    ScopedTtlUpdate scoped_update(*this);
11

            
12
1365
    std::vector<std::string> expired;
13
1365
    last_scheduled_time_ = absl::nullopt;
14

            
15
1365
    const auto now = time_source_.monotonicTime();
16
1365
    auto itr = ttls_.begin();
17
1413
    while (itr != ttls_.end() && itr->first <= now) {
18
48
      expired.push_back(itr->second);
19
48
      ttl_lookup_.erase(itr->second);
20
48
      itr++;
21
48
    }
22

            
23
1365
    if (itr != ttls_.begin()) {
24
48
      ttls_.erase(ttls_.begin(), itr);
25
48
    }
26

            
27
1365
    if (!expired.empty()) {
28
48
      callback_(expired);
29
48
    }
30
1365
  });
31
3305
}
32
144
void TtlManager::add(std::chrono::milliseconds ttl, const std::string& name) {
33
144
  ScopedTtlUpdate scoped_update(*this);
34

            
35
144
  clear(name);
36

            
37
144
  auto itr_and_inserted = ttls_.insert({time_source_.monotonicTime() + ttl, name});
38
144
  ttl_lookup_[name] = itr_and_inserted.first;
39
144
}
40

            
41
4106
void TtlManager::clear(const std::string& name) {
42
4106
  ScopedTtlUpdate scoped_update(*this);
43

            
44
4106
  auto lookup_itr = ttl_lookup_.find(name);
45
4106
  if (lookup_itr != ttl_lookup_.end()) {
46
76
    ttls_.erase(lookup_itr->second);
47
76
    ttl_lookup_.erase(lookup_itr);
48
76
  }
49
4106
}
50

            
51
7607
void TtlManager::refreshTimer() {
52
  // No TTLs, so just disable the timer.
53
7607
  if (ttls_.empty()) {
54
6175
    timer_->disableTimer();
55
6175
    return;
56
6175
  }
57

            
58
1432
  auto next_ttl_expiry = ttls_.begin()->first;
59

            
60
  // The currently scheduled timer execution matches the next TTL expiry, so do nothing.
61
1432
  if (timer_->enabled() && last_scheduled_time_ == next_ttl_expiry) {
62
30
    return;
63
30
  }
64

            
65
1402
  auto timer_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
66
1402
      next_ttl_expiry - time_source_.monotonicTime());
67

            
68
  // The time until the next TTL changed, so reset the timer to match the new value.
69
1402
  last_scheduled_time_ = next_ttl_expiry;
70
1402
  timer_->enableTimer(timer_duration, nullptr);
71
1402
}
72
} // namespace Config
73
} // namespace Envoy