/proc/self/cwd/source/common/config/ttl.h
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include <chrono> |
4 | | |
5 | | #include "envoy/event/dispatcher.h" |
6 | | #include "envoy/event/timer.h" |
7 | | |
8 | | namespace Envoy { |
9 | | namespace Config { |
10 | | |
11 | | /** |
12 | | * Class for managing TTL expiration of xDS resources. TTLs are managed with a single timer that |
13 | | * will always be set to the time until the next TTL, ensuring that we have a constant amount of |
14 | | * timers per xDS resource type. |
15 | | * |
16 | | * We use a combination of two data structures here: a std::set that ensures that we can iterate |
17 | | * over the pending TTLs in sorted over, and a map from resource name to the set iterator which |
18 | | * allows us to efficiently clear or update TTLs. As iterator stability is required to track the |
19 | | * iterators, we use std::set over something like ``absl::btree_set``. |
20 | | * |
21 | | * As a result of these two data structures, all lookups and modifications can be performed in |
22 | | * O(log (number of TTL entries)). This comes at the cost of a higher memory overhead versus just |
23 | | * using a single data structure. |
24 | | */ |
25 | | class TtlManager { |
26 | | public: |
27 | | TtlManager(std::function<void(const std::vector<std::string>&)> callback, |
28 | | Event::Dispatcher& dispatcher, TimeSource& time_source); |
29 | | |
30 | | // RAII tracker to simplify managing when we should be running the update callbacks. |
31 | | class ScopedTtlUpdate { |
32 | | public: |
33 | 448 | ~ScopedTtlUpdate() { |
34 | 448 | if (--parent_.scoped_update_counter_ == 0) { |
35 | 172 | parent_.refreshTimer(); |
36 | 172 | } |
37 | 448 | } |
38 | | |
39 | | private: |
40 | 448 | ScopedTtlUpdate(TtlManager& parent) : parent_(parent) { parent_.scoped_update_counter_++; } |
41 | | |
42 | | friend TtlManager; |
43 | | |
44 | | TtlManager& parent_; |
45 | | }; |
46 | | |
47 | 172 | ScopedTtlUpdate scopedTtlUpdate() { return {*this}; } |
48 | | |
49 | | void add(std::chrono::milliseconds ttl, const std::string& name); |
50 | | |
51 | | void clear(const std::string& name); |
52 | | |
53 | | private: |
54 | | void refreshTimer(); |
55 | | |
56 | | using TtlSet = std::set<std::pair<MonotonicTime, std::string>>; |
57 | | TtlSet ttls_; |
58 | | absl::flat_hash_map<std::string, TtlSet::iterator> ttl_lookup_; |
59 | | |
60 | | Event::TimerPtr timer_; |
61 | | absl::optional<MonotonicTime> last_scheduled_time_; |
62 | | uint8_t scoped_update_counter_{}; |
63 | | |
64 | | std::function<void(const std::vector<std::string>&)> callback_; |
65 | | Event::Dispatcher& dispatcher_; |
66 | | TimeSource& time_source_; |
67 | | }; |
68 | | } // namespace Config |
69 | | } // namespace Envoy |