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
3264
    : callback_(callback), dispatcher_(dispatcher), time_source_(time_source) {
9
4351
  timer_ = dispatcher_.createTimer([this]() {
10
1487
    ScopedTtlUpdate scoped_update(*this);
11

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

            
15
1487
    const auto now = time_source_.monotonicTime();
16
1487
    auto itr = ttls_.begin();
17
1535
    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
1487
    if (itr != ttls_.begin()) {
24
48
      ttls_.erase(ttls_.begin(), itr);
25
48
    }
26

            
27
1487
    if (!expired.empty()) {
28
48
      callback_(expired);
29
48
    }
30
1487
  });
31
3264
}
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
4022
void TtlManager::clear(const std::string& name) {
42
4022
  ScopedTtlUpdate scoped_update(*this);
43

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

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

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

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

            
65
1524
  auto timer_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
66
1524
      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
1524
  last_scheduled_time_ = next_ttl_expiry;
70
1524
  timer_->enableTimer(timer_duration, nullptr);
71
1524
}
72
} // namespace Config
73
} // namespace Envoy