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
11751
    ~ScopedTtlUpdate() {
34
11751
      if (--parent_.scoped_update_counter_ == 0) {
35
7649
        parent_.refreshTimer();
36
7649
      }
37
11751
    }
38

            
39
  private:
40
11751
    ScopedTtlUpdate(TtlManager& parent) : parent_(parent) { parent_.scoped_update_counter_++; }
41

            
42
    friend TtlManager;
43

            
44
    TtlManager& parent_;
45
  };
46

            
47
6098
  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